Add "Perpendicular to Endpoint" snapping target (#2581)
* Perpendicular snap for line's endpoints * move comment * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
435a6daf25
commit
af4f57ef38
|
|
@ -99,6 +99,7 @@ impl SnappingState {
|
||||||
PathSnapTarget::NormalToPath => self.path.normal_to_path,
|
PathSnapTarget::NormalToPath => self.path.normal_to_path,
|
||||||
PathSnapTarget::TangentToPath => self.path.tangent_to_path,
|
PathSnapTarget::TangentToPath => self.path.tangent_to_path,
|
||||||
PathSnapTarget::IntersectionPoint => self.path.path_intersection_point,
|
PathSnapTarget::IntersectionPoint => self.path.path_intersection_point,
|
||||||
|
PathSnapTarget::PerpendicularToEndpoint => self.path.perpendicular_from_endpoint,
|
||||||
},
|
},
|
||||||
SnapTarget::Artboard(_) => self.artboards,
|
SnapTarget::Artboard(_) => self.artboards,
|
||||||
SnapTarget::Grid(_) => self.grid_snapping,
|
SnapTarget::Grid(_) => self.grid_snapping,
|
||||||
|
|
@ -142,6 +143,7 @@ pub struct PathSnapping {
|
||||||
pub tangent_to_path: bool,
|
pub tangent_to_path: bool,
|
||||||
pub path_intersection_point: bool,
|
pub path_intersection_point: bool,
|
||||||
pub align_with_anchor_point: bool, // TODO: Rename
|
pub align_with_anchor_point: bool, // TODO: Rename
|
||||||
|
pub perpendicular_from_endpoint: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PathSnapping {
|
impl Default for PathSnapping {
|
||||||
|
|
@ -154,6 +156,7 @@ impl Default for PathSnapping {
|
||||||
tangent_to_path: true,
|
tangent_to_path: true,
|
||||||
path_intersection_point: true,
|
path_intersection_point: true,
|
||||||
align_with_anchor_point: true,
|
align_with_anchor_point: true,
|
||||||
|
perpendicular_from_endpoint: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -476,6 +479,7 @@ pub enum PathSnapTarget {
|
||||||
NormalToPath,
|
NormalToPath,
|
||||||
TangentToPath,
|
TangentToPath,
|
||||||
IntersectionPoint,
|
IntersectionPoint,
|
||||||
|
PerpendicularToEndpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PathSnapTarget {
|
impl fmt::Display for PathSnapTarget {
|
||||||
|
|
@ -487,6 +491,7 @@ impl fmt::Display for PathSnapTarget {
|
||||||
PathSnapTarget::NormalToPath => write!(f, "Path: Normal to Path"),
|
PathSnapTarget::NormalToPath => write!(f, "Path: Normal to Path"),
|
||||||
PathSnapTarget::TangentToPath => write!(f, "Path: Tangent to Path"),
|
PathSnapTarget::TangentToPath => write!(f, "Path: Tangent to Path"),
|
||||||
PathSnapTarget::IntersectionPoint => write!(f, "Path: Intersection Point"),
|
PathSnapTarget::IntersectionPoint => write!(f, "Path: Intersection Point"),
|
||||||
|
PathSnapTarget::PerpendicularToEndpoint => write!(f, "Path: Perp. to Endpoint"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -533,6 +538,7 @@ pub enum AlignmentSnapTarget {
|
||||||
ArtboardCenterPoint,
|
ArtboardCenterPoint,
|
||||||
AlignWithAnchorPoint,
|
AlignWithAnchorPoint,
|
||||||
IntersectionPoint,
|
IntersectionPoint,
|
||||||
|
PerpendicularToEndpoint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for AlignmentSnapTarget {
|
impl fmt::Display for AlignmentSnapTarget {
|
||||||
|
|
@ -544,6 +550,7 @@ impl fmt::Display for AlignmentSnapTarget {
|
||||||
AlignmentSnapTarget::ArtboardCenterPoint => write!(f, "{}", ArtboardSnapTarget::CenterPoint),
|
AlignmentSnapTarget::ArtboardCenterPoint => write!(f, "{}", ArtboardSnapTarget::CenterPoint),
|
||||||
AlignmentSnapTarget::AlignWithAnchorPoint => write!(f, "{}", PathSnapTarget::AnchorPointWithColinearHandles),
|
AlignmentSnapTarget::AlignWithAnchorPoint => write!(f, "{}", PathSnapTarget::AnchorPointWithColinearHandles),
|
||||||
AlignmentSnapTarget::IntersectionPoint => write!(f, "{}", PathSnapTarget::IntersectionPoint),
|
AlignmentSnapTarget::IntersectionPoint => write!(f, "{}", PathSnapTarget::IntersectionPoint),
|
||||||
|
AlignmentSnapTarget::PerpendicularToEndpoint => write!(f, "{}", PathSnapTarget::PerpendicularToEndpoint),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,13 +59,46 @@ impl AlignmentSnapper {
|
||||||
// TODO: snap handle points
|
// TODO: snap handle points
|
||||||
let document = snap_data.document;
|
let document = snap_data.document;
|
||||||
let tolerance = snap_tolerance(document);
|
let tolerance = snap_tolerance(document);
|
||||||
|
let tolerance_squared = tolerance.powi(2);
|
||||||
let mut snap_x: Option<SnappedPoint> = None;
|
let mut snap_x: Option<SnappedPoint> = None;
|
||||||
let mut snap_y: Option<SnappedPoint> = None;
|
let mut snap_y: Option<SnappedPoint> = None;
|
||||||
|
|
||||||
for target_point in self.bounding_box_points.iter().chain(unselected_geometry) {
|
for target_point in self.bounding_box_points.iter().chain(unselected_geometry) {
|
||||||
let target_position = target_point.document_point;
|
let target_position = target_point.document_point;
|
||||||
|
|
||||||
|
// Perpendicular snap for line's endpoints
|
||||||
|
if let Some(quad) = target_point.quad.map(|q| q.0) {
|
||||||
|
if quad[0] == quad[3] && quad[1] == quad[2] && quad[0] == target_point.document_point {
|
||||||
|
let [p1, p2, ..] = quad;
|
||||||
|
let direction = (p2 - p1).normalize();
|
||||||
|
let normal = DVec2::new(-direction.y, direction.x);
|
||||||
|
|
||||||
|
for endpoint in [p1, p2] {
|
||||||
|
if let Some(perpendicular_snap) = Quad::intersect_rays(point.document_point, direction, endpoint, normal) {
|
||||||
|
let distance_squared = point.document_point.distance_squared(perpendicular_snap);
|
||||||
|
if distance_squared < tolerance_squared {
|
||||||
|
let distance = distance_squared.sqrt();
|
||||||
|
let distance_to_align_target = perpendicular_snap.distance_squared(endpoint).sqrt();
|
||||||
|
|
||||||
|
let snap_point = SnappedPoint {
|
||||||
|
snapped_point_document: perpendicular_snap,
|
||||||
|
source: point.source,
|
||||||
|
target: SnapTarget::Alignment(AlignmentSnapTarget::PerpendicularToEndpoint),
|
||||||
|
target_bounds: Some(Quad(quad)),
|
||||||
|
distance,
|
||||||
|
tolerance,
|
||||||
|
distance_to_align_target,
|
||||||
|
fully_constrained: false,
|
||||||
|
at_intersection: true,
|
||||||
|
alignment_target_x: Some(endpoint),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
snap_results.points.push(snap_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let [point_on_x, point_on_y] = if let SnapConstraint::Line { origin, direction } = constraint {
|
let [point_on_x, point_on_y] = if let SnapConstraint::Line { origin, direction } = constraint {
|
||||||
[
|
[
|
||||||
Quad::intersect_rays(target_point.document_point, DVec2::Y, origin, direction),
|
Quad::intersect_rays(target_point.document_point, DVec2::Y, origin, direction),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue