Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 三角学(或者可能是精度误差?)#_C#_Math_Geometry - Fatal编程技术网

C# 三角学(或者可能是精度误差?)#

C# 三角学(或者可能是精度误差?)#,c#,math,geometry,C#,Math,Geometry,我正在尝试制作一个可以制作动画的程序——在屏幕上画一个木棍,允许用户移动手臂和腿,等等 但是,如果我想将两端相连的零件(或图形)移动到另一个零件,我也需要移动该零件,并在它们之间保持相同的角度,这样看起来会很逼真 我有这个代码(假设输入是正确的,也就是说运动部件的半径是相同的。) 问题是,在每次更新时,移动的零件(而不是基础零件)要么有其原始值(在基础零件之间),要么有一个不同的值,改变每一帧,尽管在两个帧中有一次它似乎工作正常 作为一个程序员,我可以跳过它,每帧做两次更新,但作为一个极客,我想

我正在尝试制作一个可以制作动画的程序——在屏幕上画一个木棍,允许用户移动手臂和腿,等等

但是,如果我想将两端相连的零件(或图形)移动到另一个零件,我也需要移动该零件,并在它们之间保持相同的角度,这样看起来会很逼真

我有这个代码(假设输入是正确的,也就是说运动部件的半径是相同的。)

问题是,在每次更新时,移动的零件(而不是基础零件)要么有其原始值(在基础零件之间),要么有一个不同的值,改变每一帧,尽管在两个帧中有一次它似乎工作正常

作为一个程序员,我可以跳过它,每帧做两次更新,但作为一个极客,我想知道我哪里出错了

谁有很好的几何知识,你能帮我吗

谢谢,马克。 图像(帧已计数):


虽然这不是解决您问题的方法,但我想改变的是:

    private double GetDistace(double x1, double y1, double x2, double y2)
    {
        return Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
    }
为此:

    private double GetDistace(double x1, double y1, double x2, double y2)
    {
        double xd = x1 - x2;
        doubly yd = y1 - y2;
        return Math.Sqrt(xd * xd + yd * yd);
    }
它应该比
Math.Pow

更快(可能)更准确。我知道这严格来说并不是对OPs问题的回答,但也许它可以证明是有趣的

所以我读了你的代码,试图找出问题所在,但我开始想:“我想知道OP真正需要的是a吗?”

现在我不是这方面的专家,但我想我可以展示一种构建复合视觉对象的不同方法

通过以这种方式构造对象,在旋转和平移时更容易建立和维护复杂的结构

首先定义一个抽象类形状

abstract class Shape
{
    static readonly Shape[] s_emptyChildren = new Shape[0];

    public Rect BoundingBox;
    public Transform Transform;
    public Shape[] Children = s_emptyChildren;

    public void RenderShape (DrawingContext context)
    {
        context.PushTransform (Transform ?? Transform.Identity);

        try
        {
            OnRenderShape (context);

            foreach (var shape in Children ?? s_emptyChildren)
            {
                shape.RenderShape (context);
            }
        }
        finally
        {
            context.Pop ();
        }
    }

    protected abstract void OnRenderShape (DrawingContext context);
}
  • Shape.BoundingBox是定义形状边界的矩形
  • Children是所有内部形状的数组(在您的示例中,我认为您将其称为内部部分)
  • Transform是一种转换,它指示此形状(及其子图形)如何与其父图形关联
  • OnRenderShape实现者实现此方法来渲染形状
Transform类可以表示简单和复杂的转换,例如:

// Translates (Moves) Shape 100 "pixels" to right in relation to its parent
var translation = new TranslateTransform (100, 0);
// Rotates Shape 30 degrees clockwise in relation to its parent
var rotation = new RotateTransform (30);
// Composite first translates then rotates the Shape
var composite = 
            new TransformGroup
            {
                Children =
                    new TransformCollection
                            {
                                translation,
                                rotation ,
                            },
            }
为了表达一个简单的复合对象,我们可以这样做:

static RectangleShape MakeSimpleShape()
{
    return
        new RectangleShape
            {
                BoundingBox = new Rect (-200, -200, 400, 400),
                Pen = s_redPen,
                Brush = null,
                Children =
                    new Shape[]
                        {
                            new RectangleShape
                                {
                                    BoundingBox = new Rect (-40, -40, 40, 40),
                                    Transform = new TranslateTransform (100, 100),
                                },
                        },
            };
}
如果您感兴趣的话,我做了一个完整的渲染示例(使用WPF)(MakeComplexShape基本上构建了一个递归形状到某个级别)

  • 在VisualStudio中创建新的控制台应用程序
  • 添加对WindowsBase、PresentationCore、PresentationFramework、System.Xaml的引用
  • 将代码粘贴到Program.cs中
应该可以走了

using System;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;

abstract class Shape
{
    static readonly Shape[] s_emptyChildren = new Shape[0];

    public Rect BoundingBox;
    public Transform Transform;
    public Shape[] Children = s_emptyChildren;

    public void RenderShape (DrawingContext context)
    {
        context.PushTransform (Transform ?? Transform.Identity);

        try
        {
            OnRenderShape (context);

            foreach (var shape in Children ?? s_emptyChildren)
            {
                shape.RenderShape (context);
            }
        }
        finally
        {
            context.Pop ();
        }
    }

    protected abstract void OnRenderShape (DrawingContext context);
}

sealed class RectangleShape : Shape
{
    static readonly SolidColorBrush s_defaultBrush = new SolidColorBrush (Colors.Green).FreezeIfNecessary ();

    public Pen Pen;
    public Brush Brush = s_defaultBrush;

    protected override void OnRenderShape (DrawingContext context)
    {
        context.DrawRectangle (Brush, Pen, BoundingBox);
    }
}

static class Extensions
{
    public static Color SetAlpha (this Color value, byte alpha)
    {
        return Color.FromArgb (alpha, value.R, value.G, value.B);
    }

    public static TValue FreezeIfNecessary<TValue>(this TValue value)
        where TValue : Freezable
    {
        if (value != null && value.CanFreeze)
        {
            value.Freeze ();
        }

        return value;
    }
}

class RenderShapeControl : FrameworkElement
{
    public Shape Shape;

    public Transform ShapeTransform;

    protected override void OnRender (DrawingContext drawingContext)
    {
        if (Shape != null)
        {
            try
            {
                drawingContext.PushTransform (new TranslateTransform (ActualWidth / 2, ActualHeight / 2).FreezeIfNecessary ());
                drawingContext.PushTransform (ShapeTransform ?? Transform.Identity);
                Shape.RenderShape (drawingContext);
            }
            finally
            {
                drawingContext.Pop ();
                drawingContext.Pop ();
            }
        }
    }

}

public class MainWindow : Window
{
    static readonly int[] s_childCount = new[] { 0, 5, 5, 5, 5, 5 };
    static readonly Brush s_redBrush = new SolidColorBrush (Colors.Red.SetAlpha (0x80)).FreezeIfNecessary ();
    static readonly Brush s_blueBrush = new SolidColorBrush (Colors.Blue.SetAlpha (0x80)).FreezeIfNecessary ();
    static readonly Pen s_redPen = new Pen (Brushes.Red, 2).FreezeIfNecessary ();
    static readonly Pen s_bluePen = new Pen (Brushes.Blue, 2).FreezeIfNecessary ();

    static Shape MakeInnerPart (int level, int index, int count, double outerside, double angle)
    {
        var innerSide = outerside / 3;
        return new RectangleShape
        {
            BoundingBox = new Rect (-innerSide / 2, -innerSide / 2, innerSide, innerSide),
            Pen = index == 0 ? s_bluePen : s_redPen,
            Brush = index == 0 && level > 0 ? s_redBrush : s_blueBrush,
            Children = MakeInnerParts (level - 1, innerSide),
            Transform =
                new TransformGroup
                {
                    Children =
                        new TransformCollection
                            {
                                new TranslateTransform (outerside/2, 0),
                                new RotateTransform (angle),
                            },
                }.FreezeIfNecessary (),
        };
    }

    static Shape[] MakeInnerParts (int level, double outerside)
    {
        var count = s_childCount[level];
        return Enumerable
            .Range (0, count)
            .Select (i => MakeInnerPart (level, i, count, outerside, (360.0 * i) / count))
            .ToArray ();
    }

    static RectangleShape MakeComplexShape ()
    {
        return new RectangleShape
        {
            BoundingBox = new Rect (-200, -200, 400, 400),
            Pen = s_redPen,
            Brush = null,
            Children = MakeInnerParts (3, 400),
        };
    }

    static RectangleShape MakeSimpleShape ()
    {
        return
            new RectangleShape
                {
                    BoundingBox = new Rect (-200, -200, 400, 400),
                    Pen = s_redPen,
                    Brush = null,
                    Children =
                        new Shape[]
                            {
                                new RectangleShape
                                    {
                                        BoundingBox = new Rect (-40, -40, 40, 40),
                                        Transform = new TranslateTransform (100, 100),
                                    },
                            },
                };
    }

    readonly DispatcherTimer m_dispatcher;
    readonly DateTime m_start = DateTime.Now;
    readonly RenderShapeControl m_shapeRenderer = new RenderShapeControl ();

    public MainWindow ()
    {
        AddChild (m_shapeRenderer);

        m_dispatcher = new DispatcherTimer (
            TimeSpan.FromSeconds (1 / 60),
            DispatcherPriority.ApplicationIdle,
            OnTimer,
            Dispatcher
            );
        m_dispatcher.Start ();
        m_shapeRenderer.Shape = MakeComplexShape ();
        //m_shapeRenderer.Shape = MakeSimpleShape ();
    }

    void OnTimer (object sender, EventArgs e)
    {
        var diff = DateTime.Now - m_start;
        var phase = (20 * diff.TotalSeconds) % 360.0;

        m_shapeRenderer.ShapeTransform =
            new TransformGroup
            {
                Children =
                    new TransformCollection
                        {
                            new TranslateTransform (100, 0),
                            new RotateTransform (phase),

                        },
            }.FreezeIfNecessary ();
        m_shapeRenderer.InvalidateVisual ();
    }
}

class Program
{
    [STAThread]
    static void Main (string[] args)
    {
        var mainWindow = new MainWindow ();
        mainWindow.ShowDialog ();
    }
}
使用系统;
使用System.Linq;
使用System.Windows;
使用System.Windows.Media;
使用System.Windows.Threading;
抽象类形状
{
静态只读形状[]s_emptyChildren=新形状[0];
公共矩形边界框;
公共转型;
public Shape[]Children=s_emptyChildren;
公共空心渲染形状(DrawingContext上下文)
{
context.PushTransform(Transform??Transform.Identity);
尝试
{
OnRenderShape(上下文);
foreach(儿童中的变量形状??空儿童)
{
shape.RenderShape(上下文);
}
}
最后
{
Pop();
}
}
渲染形状上受保护的抽象无效(DrawingContext上下文);
}
密封类矩形形状:形状
{
静态只读SolidColorBrush s_defaultBrush=新的SolidColorBrush(Colors.Green);
公共钢笔;
公共画笔画笔=s_默认画笔;
受保护的覆盖在RenderShape上无效(DrawingContext上下文)
{
context.DrawRectangle(画笔、画笔、边框);
}
}
静态类扩展
{
公共静态颜色SetAlpha(此颜色值,字节alpha)
{
返回Color.FromArgb(alpha,value.R,value.G,value.B);
}
公共静态TValue冻结(如有必要)(此TValue值)
其中TValue:Freezable
{
if(value!=null&&value.CanFreeze)
{
value.Freeze();
}
返回值;
}
}
类RenderShapeControl:FrameworkElement
{
公共形态;
公共变换形状变换;
受保护的重写void OnRender(DrawingContext DrawingContext)
{
if(Shape!=null)
{
尝试
{
drawingContext.PushTransform(新的TranslateTransform(ActualWidth/2,ActualHeight/2).freezeIfEssential());
drawingContext.PushTransform(ShapeTransform??Transform.Identity);
Shape.RenderShape(drawingContext);
}
最后
{
Pop();
Pop();
}
}
}
}
公共类主窗口:窗口
{
静态只读int[]s_childCount=new[]{0,5,5,5,5};
静态只读画笔s_redBrush=新的SolidColorBrush(Colors.Red.SetAlpha(0x80)).freezeifEssential();
静态只读画笔s_blueBrush=新的SolidColorBrush(Colors.Blue.SetAlpha(0x80)).freezeifEssential();
静态只读画笔s_redPen=新画笔(brush.Red,2)。如有必要,冻结();
static readonly Pen s_bluePen=新笔(brush.Blue,2)。如有必要,冻结();
静态形状MakeInnerPart(整数级别、整数索引、整数计数、双外侧、双角度)
{
var innerSide=outerside/3;
返回新的矩形形状
{
BoundingBox=新矩形(-innerSide/2,-innerSide/2,innerSide,innerSide),
钢笔=索引==0?蓝色钢笔:红色钢笔,
画笔=索引==0&&level>0?s_红画笔:s_蓝画笔,
子项=MakeInnerParts(级别-1,内侧),
转化=
新转型集团
{
孩子们=
新变形金刚系列
using System;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;

abstract class Shape
{
    static readonly Shape[] s_emptyChildren = new Shape[0];

    public Rect BoundingBox;
    public Transform Transform;
    public Shape[] Children = s_emptyChildren;

    public void RenderShape (DrawingContext context)
    {
        context.PushTransform (Transform ?? Transform.Identity);

        try
        {
            OnRenderShape (context);

            foreach (var shape in Children ?? s_emptyChildren)
            {
                shape.RenderShape (context);
            }
        }
        finally
        {
            context.Pop ();
        }
    }

    protected abstract void OnRenderShape (DrawingContext context);
}

sealed class RectangleShape : Shape
{
    static readonly SolidColorBrush s_defaultBrush = new SolidColorBrush (Colors.Green).FreezeIfNecessary ();

    public Pen Pen;
    public Brush Brush = s_defaultBrush;

    protected override void OnRenderShape (DrawingContext context)
    {
        context.DrawRectangle (Brush, Pen, BoundingBox);
    }
}

static class Extensions
{
    public static Color SetAlpha (this Color value, byte alpha)
    {
        return Color.FromArgb (alpha, value.R, value.G, value.B);
    }

    public static TValue FreezeIfNecessary<TValue>(this TValue value)
        where TValue : Freezable
    {
        if (value != null && value.CanFreeze)
        {
            value.Freeze ();
        }

        return value;
    }
}

class RenderShapeControl : FrameworkElement
{
    public Shape Shape;

    public Transform ShapeTransform;

    protected override void OnRender (DrawingContext drawingContext)
    {
        if (Shape != null)
        {
            try
            {
                drawingContext.PushTransform (new TranslateTransform (ActualWidth / 2, ActualHeight / 2).FreezeIfNecessary ());
                drawingContext.PushTransform (ShapeTransform ?? Transform.Identity);
                Shape.RenderShape (drawingContext);
            }
            finally
            {
                drawingContext.Pop ();
                drawingContext.Pop ();
            }
        }
    }

}

public class MainWindow : Window
{
    static readonly int[] s_childCount = new[] { 0, 5, 5, 5, 5, 5 };
    static readonly Brush s_redBrush = new SolidColorBrush (Colors.Red.SetAlpha (0x80)).FreezeIfNecessary ();
    static readonly Brush s_blueBrush = new SolidColorBrush (Colors.Blue.SetAlpha (0x80)).FreezeIfNecessary ();
    static readonly Pen s_redPen = new Pen (Brushes.Red, 2).FreezeIfNecessary ();
    static readonly Pen s_bluePen = new Pen (Brushes.Blue, 2).FreezeIfNecessary ();

    static Shape MakeInnerPart (int level, int index, int count, double outerside, double angle)
    {
        var innerSide = outerside / 3;
        return new RectangleShape
        {
            BoundingBox = new Rect (-innerSide / 2, -innerSide / 2, innerSide, innerSide),
            Pen = index == 0 ? s_bluePen : s_redPen,
            Brush = index == 0 && level > 0 ? s_redBrush : s_blueBrush,
            Children = MakeInnerParts (level - 1, innerSide),
            Transform =
                new TransformGroup
                {
                    Children =
                        new TransformCollection
                            {
                                new TranslateTransform (outerside/2, 0),
                                new RotateTransform (angle),
                            },
                }.FreezeIfNecessary (),
        };
    }

    static Shape[] MakeInnerParts (int level, double outerside)
    {
        var count = s_childCount[level];
        return Enumerable
            .Range (0, count)
            .Select (i => MakeInnerPart (level, i, count, outerside, (360.0 * i) / count))
            .ToArray ();
    }

    static RectangleShape MakeComplexShape ()
    {
        return new RectangleShape
        {
            BoundingBox = new Rect (-200, -200, 400, 400),
            Pen = s_redPen,
            Brush = null,
            Children = MakeInnerParts (3, 400),
        };
    }

    static RectangleShape MakeSimpleShape ()
    {
        return
            new RectangleShape
                {
                    BoundingBox = new Rect (-200, -200, 400, 400),
                    Pen = s_redPen,
                    Brush = null,
                    Children =
                        new Shape[]
                            {
                                new RectangleShape
                                    {
                                        BoundingBox = new Rect (-40, -40, 40, 40),
                                        Transform = new TranslateTransform (100, 100),
                                    },
                            },
                };
    }

    readonly DispatcherTimer m_dispatcher;
    readonly DateTime m_start = DateTime.Now;
    readonly RenderShapeControl m_shapeRenderer = new RenderShapeControl ();

    public MainWindow ()
    {
        AddChild (m_shapeRenderer);

        m_dispatcher = new DispatcherTimer (
            TimeSpan.FromSeconds (1 / 60),
            DispatcherPriority.ApplicationIdle,
            OnTimer,
            Dispatcher
            );
        m_dispatcher.Start ();
        m_shapeRenderer.Shape = MakeComplexShape ();
        //m_shapeRenderer.Shape = MakeSimpleShape ();
    }

    void OnTimer (object sender, EventArgs e)
    {
        var diff = DateTime.Now - m_start;
        var phase = (20 * diff.TotalSeconds) % 360.0;

        m_shapeRenderer.ShapeTransform =
            new TransformGroup
            {
                Children =
                    new TransformCollection
                        {
                            new TranslateTransform (100, 0),
                            new RotateTransform (phase),

                        },
            }.FreezeIfNecessary ();
        m_shapeRenderer.InvalidateVisual ();
    }
}

class Program
{
    [STAThread]
    static void Main (string[] args)
    {
        var mainWindow = new MainWindow ();
        mainWindow.ShowDialog ();
    }
}
angle = angleof(part.XY relative part.baseXY) - angleof(this.baseXY relative this.XY)
angle = 2*pi - angle + angleof(this.XY relative this.baseXY)
angle = angleof(part.XY relative part.baseXY) + angleof(this.XY relative this.baseXY) - angleof(new.XY relative this.baseXY)
part.baseXY = new.XY
part.XY = part.baseXY + radius * cos/sin(angle)