Нужна помощь в написании методов преобразования между 2D и 3D (Point3DToPoint и PointAndZToPoint3D) - PullRequest
3 голосов
/ 29 апреля 2010

Я новичок в WPF 3D, так что, может быть, я просто упускаю что-то очевидное, но как мне преобразовать из 3D в 2D и (для заданного местоположения z) из 2D в 3D?

В частности, мне нужно два метода преобразования:

  • Point3DToPoint - Если у меня есть координата (x, y, z) в трехмерном мире, как определить координату (x, y) на проецируемой 2D-поверхности. Подпись метода: public Point Point3DToPoint(Point3D point3D)

  • PointAndZToPoint3D - Если у меня есть координаты (x, y) на проецируемой 2D-поверхности и az в 3D-мире, как определить (x координаты в трехмерном мире? Подпись метода: public Point3D PointAndZToPoint3D(Point point, double z)

Мне бы хотелось, чтобы 2D-координата была местоположением, измеренным от верхнего левого угла Viewport3D, а 3D-координата - местоположением относительно начала координат ( 0, 0, 0) трехмерного мира.

Примечание 1: я нашел этот связанный вопрос , но он касается только преобразования из 3D в 2D (не наоборот), и я не уверен, что ответы актуальны.

Примечание 2. В настоящее время я использую .NET 3.5, но если в .NET 4.0 есть улучшения, которые могут мне помочь, пожалуйста, дайте мне знать.

1 Ответ

4 голосов
/ 01 мая 2010

3D-библиотека Чарльза Петцольда, которую можно загрузить здесь в разделе "Библиотека Petzold.Media3D", содержит класс ViewportInfo с этими двумя статическими методами:

  • public static Point Point3DToPoint2D(Viewport3D viewport, Point3d point)

  • public static bool Point2DToPoint3D(Viewport3D viewport, Point, ptIn, out LineRange range)

Point2DToPoint3D не является точным соответствием для PointAndZToPoint3D(), потому что он возвращает (через параметр out) LineRange, а не конкретную точку, но так уж получилось, что LineRange имеет метод PointFromZ(double zValue), которая обеспечивает точку, где луч пересекает плоскость, определенную как z = zValue.

Пример кода:

using System.Windows;
using System.Windows.Input;
using Petzold.Media3D;

namespace _3DTester
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        /* This MouseDown event handler prints:
          (1) the current position of the mouse
          (2) the 3D mouse location on the ground plane (z = 0)
          (3) the 2D mouse location converted from the 3D location */

        private void Window_MouseDown(object sender, MouseEventArgs e)
        {
            var range = new LineRange();
            var isValid = ViewportInfo.Point2DtoPoint3D(Viewport, e.GetPosition(Viewport), out range);
            if (!isValid)
                MouseLabel.Content = "(no data)";
            else
            {
                var point3D = range.PointFromZ(0);
                var point = ViewportInfo.Point3DtoPoint2D(Viewport, point3D);
                MouseLabel.Content = e.GetPosition(Viewport) + "\n" + point3D + "\n" + point;
            }
        }
    }
}

XAML код

<Window
    x:Class="_3DTester.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    Height="300"
    Width="300"
    MouseDown="Window_MouseDown">
    <Grid>
        <Viewport3D Name="Viewport">
            <Viewport3D.Camera>
                <PerspectiveCamera
                    Position="0,0,30"
                    LookDirection="0,0,-1" 
                    UpDirection="0,1,0" />
            </Viewport3D.Camera>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <Model3DGroup>
                        <DirectionalLight Color="White" Direction="1,-1,-1" />
                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <MeshGeometry3D
                                    Positions="0,0,10 -5,-5,0 -5,5,0 5,5,0 5,-5,0"
                                    TriangleIndices="2 1 0  2 0 3  4 3 0  1 4 0" />
                            </GeometryModel3D.Geometry>
                            <GeometryModel3D.Material>
                                <DiffuseMaterial Brush="Red" />
                            </GeometryModel3D.Material>
                        </GeometryModel3D>
                    </Model3DGroup>
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D>
        <Label Name="MouseLabel" Content="(no data)" />
    </Grid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...