首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WPF ModelVisual3D的可见二维内容边界

WPF ModelVisual3D的可见二维内容边界
EN

Stack Overflow用户
提问于 2017-10-14 02:07:41
回答 2查看 1.2K关注 0票数 3

在WPF中,我们可以很容易地使用VisualTreeHelper.GetDescendantBounds(Viewport3D)获得不需要转换的ModelVisual3D的可见2D内容边界。但是,当ModelVisual3D转换时,GetDescendantBounds返回比可见内容更大的边界。如何获得可见内容的精确界限?

代码-xaml:

代码语言:javascript
复制
<Grid Background="LightGray">
    <Viewport3D x:Name="MyViewport">
        <Viewport3D.Camera>
            <OrthographicCamera Position="3 3 5" LookDirection="-3 -3 -5" Width="3"/>
        </Viewport3D.Camera>
        <Viewport3D.Children>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <DirectionalLight Color="White" Direction="-1 -1 -1"/>
                </ModelVisual3D.Content>
            </ModelVisual3D>
            <ModelVisual3D x:Name="MyVisual">
                <ModelVisual3D.Content>
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D Positions="0,0,0 1,0,0 0,1,0 1,1,0 0,0,1 1,0,1 0,1,1 1,1,1"
                                            TriangleIndices="0,2,1 1,2,3 0,4,2 2,4,6 0,1,4 1,5,4 1,7,5 1,3,7 4,5,6 7,6,5 2,6,3 3,6,7"/>
                        </GeometryModel3D.Geometry>
                        <GeometryModel3D.Material>
                            <DiffuseMaterial Brush="Red"/>
                        </GeometryModel3D.Material>
                        <!--<GeometryModel3D.Transform>
                            <RotateTransform3D>
                                <RotateTransform3D.Rotation>
                                    <AxisAngleRotation3D Axis="1 1 0" Angle="5"/>
                                </RotateTransform3D.Rotation>
                            </RotateTransform3D>
                        </GeometryModel3D.Transform>-->
                    </GeometryModel3D>
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D.Children>
    </Viewport3D>
    <Rectangle x:Name="MyRegion" Stroke="Blue" StrokeThickness="1" VerticalAlignment="Top" HorizontalAlignment="Left"/>
</Grid>

代号:

代码语言:javascript
复制
var bounds = VisualTreeHelper.GetDescendantBounds(MyViewport);

MyRegion.Width = bounds.Width;
MyRegion.Height = bounds.Height;

MyRegion.Margin = new Thickness(bounds.Left, bounds.Top, 0, 0);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-16 01:52:02

如果您可以很容易地找到所有的三角形点,在您的网格几何没有性能问题,您可以尝试下面的方法。我所做的就是将所有的Point3Ds转换成2D坐标,并得到所有2D点的边界。

代码语言:javascript
复制
GeneralTransform3DTo2D transform = MyVisual.TransformToAncestor(MyViewport);
MeshGeometry3D geometry = (MeshGeometry3D) ((GeometryModel3D) MyVisual.Content).Geometry;
Rect wholeBounds = Rect.Empty;
if (transform != null)
{
    for (int i = 0; i < geometry.TriangleIndices.Count;)
    {
        Polygon p = new Polygon
        {
            Stroke = Brushes.Blue,
            StrokeThickness = 0.25
        };
        var tr = ((GeometryModel3D) MyVisual.Content).Transform;
        p.Points.Add(transform.Transform(tr.Transform(geometry.Positions[geometry.TriangleIndices[i++]])));
        p.Points.Add(transform.Transform(tr.Transform(geometry.Positions[geometry.TriangleIndices[i++]])));
        p.Points.Add(transform.Transform(tr.Transform(geometry.Positions[geometry.TriangleIndices[i++]])));
        foreach (Point point in p.Points)
        {
            wholeBounds.Union(point);
        }
    }
    MyRegion.Width = wholeBounds.Width;
    MyRegion.Height = wholeBounds.Height;

    MyRegion.Margin = new Thickness(wholeBounds.Left, wholeBounds.Top, 0, 0);
}

票数 2
EN

Stack Overflow用户

发布于 2017-10-16 13:52:14

我改进了@walterlv的方法以满足更复杂的层次结构。

代码语言:javascript
复制
private void MainWindow_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    var bounds = CalculateBounds(MyVisual);

    MyRegion.Width = bounds.Width;
    MyRegion.Height = bounds.Height;

    MyRegion.Margin = new Thickness(bounds.Left, bounds.Top, 0, 0);
}

public static Viewport3DVisual GetViewport3DVisual(Visual3D visual3D)
{
    DependencyObject obj = visual3D;

    while (obj != null)
    {
        var visual = obj as Viewport3DVisual;
        if (visual != null)
        {
            return visual;
        }

        obj = VisualTreeHelper.GetParent(obj);
    }

    return null;
}

public static Rect CalculateBounds(Visual3D visual)
{
    var transform = visual.TransformToAncestor(GetViewport3DVisual(visual));
    if (transform == null)
    {
        return Rect.Empty;
    }

    var bounds = Rect.Empty;

    var modelVisual3D = visual as ModelVisual3D;
    if (modelVisual3D != null)
    {
        bounds.Union(CalculateBounds(transform, modelVisual3D.Content, Matrix3D.Identity));

        // Unio the bounds of Children
        foreach (var child in modelVisual3D.Children)
        {
            bounds.Union(CalculateBounds(child));
        }
    }
    else
    {
        // UIElement3D or Viewport2DVisual3D 
        bounds.Union(transform.TransformBounds(VisualTreeHelper.GetDescendantBounds(visual)));
    }

    return bounds;
}

public static Rect CalculateBounds(GeneralTransform3DTo2D transform, Model3D model, Matrix3D rootMatrix)
{
    var region = Rect.Empty;
    var matrix = Matrix3D.Identity;

    matrix.Prepend(rootMatrix);
    if (model.Transform != null)
    {
        matrix.Prepend(model.Transform.Value);
    }

    var geometryModel3D = model as GeometryModel3D;
    if (geometryModel3D != null)
    {
        var meshGeometry3D = geometryModel3D.Geometry as MeshGeometry3D;
        if (meshGeometry3D != null)
        {
            var innerTransform = new MatrixTransform3D(matrix);
            foreach (var position in meshGeometry3D.Positions)
            {
                region.Union(transform.Transform(innerTransform.Transform(position)));
            }
        }
    }
    else
    {
        var model3DGroup = model as Model3DGroup;
        if (model3DGroup != null)
        {
            foreach (var child in model3DGroup.Children)
            {
                region.Union(CalculateBounds(transform, child, matrix));
            }
        }
    }

    return region;
} 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46740152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档