Fix alignment snapping not preserving aspect ratio when Shift is held (#2062)

Fix align with a diagonal constraint
This commit is contained in:
James Lindsay 2024-10-26 01:34:23 +01:00 committed by GitHub
parent 7fc0a593c8
commit 79408fc0cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 50 additions and 46 deletions

View File

@ -62,28 +62,20 @@ impl AlignmentSnapper {
let document = snap_data.document; let document = snap_data.document;
let tolerance = snap_tolerance(document); let tolerance = snap_tolerance(document);
let mut consider_x = true;
let mut consider_y = true;
if let SnapConstraint::Line { direction, .. } = constraint {
let direction = direction.normalize_or_zero();
if direction.x.abs() < 1e-5 {
consider_y = false;
} else if direction.y.abs() < 1e-5 {
consider_x = false;
}
}
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;
let point_on_x = DVec2::new(point.document_point.x, target_position.y); let [point_on_x, point_on_y] = if let SnapConstraint::Line { origin, direction } = constraint {
let dist_x = (target_position.y - point.document_point.y).abs(); [
Quad::intersect_rays(target_point.document_point, DVec2::Y, origin, direction),
let point_on_y = DVec2::new(target_position.x, point.document_point.y); Quad::intersect_rays(target_point.document_point, DVec2::X, origin, direction),
let dist_y = (target_position.x - point.document_point.x).abs(); ]
} else {
[DVec2::new(point.document_point.x, target_position.y), DVec2::new(target_position.x, point.document_point.y)].map(Some)
};
let target_geometry = matches!(target_point.target, SnapTarget::Geometry(_)); let target_geometry = matches!(target_point.target, SnapTarget::Geometry(_));
let updated_target = if target_geometry { let updated_target = if target_geometry {
@ -92,38 +84,48 @@ impl AlignmentSnapper {
target_point.target target_point.target
}; };
if consider_x && dist_x < tolerance && snap_x.as_ref().map_or(true, |point| dist_y < point.distance_to_align_target) { if let Some(point_on_x) = point_on_x {
let distance_to_snapped = point.document_point.distance(point_on_x);
let distance_to_align_target = point_on_x.distance(target_position);
if distance_to_snapped < tolerance && snap_x.as_ref().map_or(true, |point| distance_to_align_target < point.distance_to_align_target) {
snap_x = Some(SnappedPoint { snap_x = Some(SnappedPoint {
snapped_point_document: point_on_x, snapped_point_document: point_on_x,
source: point.source, //ToDo map source source: point.source, //ToDo map source
target: updated_target, target: updated_target,
target_bounds: target_point.quad, target_bounds: target_point.quad,
distance: dist_x, distance: distance_to_snapped,
tolerance, tolerance,
distance_to_align_target: dist_y, distance_to_align_target,
alignment_target_x: Some(target_position), alignment_target_x: Some(target_position),
fully_constrained: true, fully_constrained: true,
at_intersection: matches!(constraint, SnapConstraint::Line { .. }),
..Default::default() ..Default::default()
}); });
} }
if consider_y && dist_y < tolerance && snap_y.as_ref().map_or(true, |point| dist_x < point.distance_to_align_target) { }
if let Some(point_on_y) = point_on_y {
let distance_to_snapped = point.document_point.distance(point_on_y);
let distance_to_align_target = point_on_y.distance(target_position);
if distance_to_snapped < tolerance && snap_y.as_ref().map_or(true, |point| distance_to_align_target < point.distance_to_align_target) {
snap_y = Some(SnappedPoint { snap_y = Some(SnappedPoint {
snapped_point_document: point_on_y, snapped_point_document: point_on_y,
source: point.source, //ToDo map source source: point.source, //ToDo map source
target: updated_target, target: updated_target,
target_bounds: target_point.quad, target_bounds: target_point.quad,
distance: dist_y, distance: distance_to_snapped,
tolerance, tolerance,
distance_to_align_target: dist_x, distance_to_align_target,
alignment_target_y: Some(target_position), alignment_target_y: Some(target_position),
fully_constrained: true, fully_constrained: true,
at_intersection: matches!(constraint, SnapConstraint::Line { .. }),
..Default::default() ..Default::default()
}); });
} }
} }
}
match (snap_x, snap_y) { match (snap_x, snap_y) {
(Some(snap_x), Some(snap_y)) => { (Some(snap_x), Some(snap_y)) if !matches!(constraint, SnapConstraint::Line { .. }) => {
let intersection = DVec2::new(snap_y.snapped_point_document.x, snap_x.snapped_point_document.y); let intersection = DVec2::new(snap_y.snapped_point_document.x, snap_x.snapped_point_document.y);
let distance = intersection.distance(point.document_point); let distance = intersection.distance(point.document_point);
@ -142,12 +144,14 @@ impl AlignmentSnapper {
alignment_target_x: snap_x.alignment_target_x, alignment_target_x: snap_x.alignment_target_x,
alignment_target_y: snap_y.alignment_target_y, alignment_target_y: snap_y.alignment_target_y,
constrained: true, constrained: true,
at_intersection: true,
..Default::default() ..Default::default()
}); });
} }
(Some(snap_x), None) => snap_results.points.push(snap_x), (Some(snap_x), Some(snap_y)) => snap_results.points.push(if snap_x.distance < snap_y.distance { snap_x } else { snap_y }),
(None, Some(snap_y)) => snap_results.points.push(snap_y), (Some(snap_x), _) => snap_results.points.push(snap_x),
(None, None) => {} (_, Some(snap_y)) => snap_results.points.push(snap_y),
_ => {}
} }
} }
pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults) { pub fn free_snap(&mut self, snap_data: &mut SnapData, point: &SnapCandidatePoint, snap_results: &mut SnapResults) {