【问题标题】:Rotated shape points after resizing inside canvas在画布内调整大小后旋转的形状点
【发布时间】:2023-02-25 02:31:36
【问题描述】:

我正在开发一个应用程序,其中我有一个 Canvas 控件,用户可以添加一条或多条线和/或一个矩形形状并将它们分组。分组后,用户可以使用鼠标事件调整父组的大小。类似于 Microsoft powerpoint 允许用户添加形状并对它们进行分组的方式。

画布内形状的层次结构

    • 角度为 30 的矩形
    • 粗细为 10、角度为 45 的线

对于组和子形状我有以下信息: Top_Left Point:形状的顶部,左侧位置,即使旋转形状也将保持不变的参考点

Point_1_Top_Left:形状的顶部、左侧位置,将根据形状的角度变化 Point_2_Top_Right:形状的顶部,右侧位置将根据形状的角度而变化 Point_3_Bottom_Right:底部,形状的右侧位置,将根据形状的角度而变化 Point_4_Bottom_Left:形状的底部、左侧位置,将根据形状的角度变化

宽度:形状的宽度 高度:形状的高度 Shape_Center:形状的中心点(宽/2,高/2)

我正在使用 RotateTransform 来实现 0.5、0.5 的旋转。我正在使用以下逻辑来计算围绕另一个点旋转一个角度的点的位置。

        public static PointF RotatePointAroundByAngle(PointF pointToRotate, PointF centerPoint, double angleInDegrees)
        {
            double angleInRadians = angleInDegrees * (Math.PI / 180);
            double cosTheta = Math.Cos(angleInRadians);
            double sinTheta = Math.Sin(angleInRadians);

            return new PointF
            {
                X = (float) Math.Round((cosTheta * (pointToRotate.X - centerPoint.X) - sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X),2),
                Y = (float)Math.Round((sinTheta * (pointToRotate.X - centerPoint.X) + cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y),2)
            };
        }

现在,如果通过宽度 Delth_Width 和高度 Delta_Height 调整组矩形的大小,我如何计算子形状的新旋转点及其宽度/高度?

谢谢, 英石

  • 我试过: 使用上述函数RotatePointAroundByAngle 更新旋转形状的位置并允许用户对它们进行分组。 现在,在调整父组的大小后,需要知道找到所有新形状点及其新宽度/高度的步骤和计算逻辑。

【问题讨论】:

    标签: c# wpf math geometry rotation


    【解决方案1】:

    已经存在一个 API 来进行所有的计算和转换。
    只需使用当前几何的 Shape.GeometryTransform 应用矩阵变换。
    在将当前的RenderTransform 应用于任何PointRect 之后,您可以使用此Transform 获得最终结果。

    以下示例显示如何转换 Shape(旋转和缩放)以及如何获取 Shape 的新转换位置。
    为了支持缩放和旋转,RenderTransform对象是一个TransformGroup,包含一个RotateTransform和一个ScaleTransform

    主窗口.xaml

    <Window>
      <Canvas x:Name="ShapeContainer"  />
    </Window>
    

    主窗口.xaml.cs

    private void OnLoaded(object sender, RoutedEventArgs e)
    {
      CreateAndShowRectangle(new Size(50, 50), new Point(200, 200), Brushes.DarkRed);
      var shape = this.ShapeContainer.Children
        .OfType<Shape>()
        .First();
    
      // Transform the shape:
      // rotate clockwise by 135 and inflate by factor 2 (200%)
      TransformShape(shape, 135, new Vector(2, 2));
    
      Point transformedShapeLocation = GetTransformedLocationOfShape(shape);
    }
    
    private void CreateAndShowRectangle(Size size, Point position, Brush fill)
    {
      var rectangleShape = new Rectangle() 
      { 
        Height = size.Height, 
        Width = size.Width, 
        Fill = fill, 
        RenderTransformOrigin = new Point(0.5, 0.5) 
      };
    
      var transformGroup = new TransformGroup();
      transformGroup.Children.Add(new RotateTransform());
      transformGroup.Children.Add(new ScaleTransform());
      rectangleShape.RenderTransform = transformGroup;
    
      Canvas.SetTop(rectangleShape, position.Y);
      Canvas.SetLeft(rectangleShape, position.X);
      this.ShapeContainer.Children.Add(rectangleShape);
    }
    
    private void TransformShape(Shape shape, double rotationAngle, Vector resizeFactor)
    {
      (shape.RenderTransform as TransformGroup).Children.OfType<RotateTransform>().First().Angle = rotationAngle;
      (shape.RenderTransform as TransformGroup).Children.OfType<ScaleTransform>().First().ScaleX = resizeFactor.X;
      (shape.RenderTransform as TransformGroup).Children.OfType<ScaleTransform>().First().ScaleY = resizeFactor.Y;
    }
    
    private Point GetTransformedLocationOfShape(Shape shape)
    {
      Point originalLocation = shape.RenderedGeometry.Bounds.Location;
    
      // Calculate the new Point based on the current RenderTransform (the TransformGroup in this case).
      // Alternatively, use the Transform.TransformBounds method.
      Point transformedLocation = shape.GeometryTransform.Transform(originalLocation);
    
      // Translate location relative to the containing Canvas
      return shape.TranslatePoint(transformedLocation, this.ShapeContainer);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多