通过用光标拖动一个角来绕其中心旋转矩形

问题描述 投票:0回答:1

我正在实现使用角手柄旋转形状的功能。旋转对于方形形状效果很好,但我遇到了非方形形状(纵横比不同于 1:1 的矩形)的问题。当通过拖动角手柄来旋转这些形状时,它们会意外地“捕捉”或旋转,而不考虑形状的纵横比。这会导致光标的初始单击点和形状的旋转行为之间不对齐。

我怀疑问题出在我的旋转计算上,没有考虑纵横比,导致旋转时角度偏移不正确。

如何正确计算旋转,同时考虑形状的长宽比,以确保用户旋转非方形形状时平滑且符合预期的行为?

也许我也在尝试解决问题中的问题,所以我要解决的核心问题基本上是如何通过角手柄绕中心旋转矩形。您可以在此视频中看到该行为。

代码:

pub fn handle_rotating(
    composition: &CompositionRes,
    selected_nodes_query: &mut Query<
        (
            &mut RelativeTransformMixin,
            &AbsoluteTransformMixin,
            &mut DimensionMixin,
        ),
        With<Selected>,
    >,
    event: &CursorMovedOnComposition,
    corner: u8,
    initial_rotation: f32,
) {
    let CursorMovedOnComposition {
        position: cursor_position,
        ..
    } = event;
    let cursor_position = transform_point_to_view_box(composition, cursor_position, true);

    selected_nodes_query.for_each_mut(
        |(mut relative_transform_mixin, absolute_transform_mixin, dimension_mixin)| {
            let relative_pivot_point = Vec2::new(
                dimension_mixin.width as f32 / 2.0,
                dimension_mixin.height as f32 / 2.0,
            );
            let absolute_pivot_point =
                apply_transform_to_point(absolute_transform_mixin.0, relative_pivot_point);

            // Determine rotation offset based on corner
            let rotation_offset_in_radians: f32 = match corner {
                _ if corner == (HandleSide::Top as u8 | HandleSide::Left as u8) => {
                    (-135.0 as f32).to_radians()
                }
                _ if corner == (HandleSide::Top as u8 | HandleSide::Right as u8) => {
                    (-45.0 as f32).to_radians()
                }
                _ if corner == (HandleSide::Bottom as u8 | HandleSide::Right as u8) => {
                    (45.0 as f32).to_radians()
                }
                _ if corner == (HandleSide::Bottom as u8 | HandleSide::Left as u8) => {
                    (135.0 as f32).to_radians()
                }
                _ => 0.0,
            };

            // Calculate rotation based on the corner
            let rotation_angle =
                calculate_rotation(initial_rotation, &cursor_position, &absolute_pivot_point);
            let final_rotation_angle =
                rotation_angle + rotation_offset_in_radians - initial_rotation;
            relative_transform_mixin.0 = set_rotation(
                relative_transform_mixin.0,
                final_rotation_angle,
                relative_pivot_point,
            );
        },
    );
}

fn calculate_rotation(
    initial_angle_in_radians: f32,
    cursor_point: &Vec2,
    pivot_point: &Vec2,
) -> f32 {
    // Calculate the angle from the pivot point to the current cursor position
    let current_angle = (cursor_point.y - pivot_point.y).atan2(cursor_point.x - pivot_point.x);

    // Calculate the raw angle difference
    let angle_diff = current_angle - initial_angle_in_radians;

    return -angle_diff;
}
math rust graphics geometry linear-algebra
1个回答
0
投票

rotation_offset_in_radians
值设置错误。与各个角对应的角度假定形状是正方形,因此,从中心看,角间隔开90度。这在矩形中是不正确的:

您需要做的是使用矩形的长宽比(或其实际尺寸,没有区别),并结合例如

atan2
找出每个角对应的角度。

当宽度和高度相同时,这会给出与原始代码相同的角度:

let width: f32 = dimension_mixin.width as f32;
let height: f32 = dimension_mixin.height as f32;
let rotation_offset_in_radians: f32 = match corner {
    _ if corner == (HandleSide::Top as u8 | HandleSide::Left as u8) => f32::atan2(-height, -width),
    _ if corner == (HandleSide::Top as u8 | HandleSide::Right as u8) => f32::atan2(-height, width),
    _ if corner == (HandleSide::Bottom as u8 | HandleSide::Right as u8) => f32::atan2(height, width),
    _ if corner == (HandleSide::Bottom as u8 | HandleSide::Left as u8) => f32::atan2(height, -width),
    _ => 0.0,
};
© www.soinside.com 2019 - 2024. All rights reserved.