65.9K
CodeProject 正在变化。 阅读更多。
Home

在 WPF 中绘制一个网格覆盖的圆柱体

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (8投票s)

2012年1月27日

CPOL

3分钟阅读

viewsIcon

46039

downloadIcon

2015

一个简单的程序,用于在 2D 中绘制一系列几何图形,这些图形代表一个网格覆盖的 3 维圆柱体。

GridShapes

引言

这是一个简单、初学者级别的项目,它从用户那里获取一些尺寸,然后使用仅 2D 几何图形绘制 3 维圆柱体的表示。这里涵盖了基本概念,例如简单的数据绑定和属性更改通知,以及简单的 Geometry 和 Path 对象。

源代码中包含的项目除了各种大小圆柱体的图形显示之外,没有其他用途。本文的目的是提供一个基本的 WPF 窗口的起点,以及在 Canvas 对象上进行基本图形绘制的起点。从这个简单的基础出发,可以添加大量的特性和选项,使这个项目更有用。

背景

这个项目/文章对我来说有两个目的

  1. 我终于要学习 C# 了。我多年来一直是 VB 程序员,所以这是一个快速而简单的入门项目。
  2. 我需要复习一下我在 WPF 中的 2D 绘图技能。

我也对 StackOverflow 上提出的一个问题很感兴趣,这个问题提出了这种类型的问题。它看起来很有趣,足以想出一个完整的解决方案。

Using the Code

WPF 中的窗口布局非常基本

<Grid>
    <Grid.Background>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FFBABABA" Offset="1" />
            <GradientStop Color="#FFE5E5E5" Offset="0" />
        </LinearGradientBrush>
    </Grid.Background>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0" Margin="10,0">
        <TextBlock Margin="10" Text="Draw a cylinder with gridlines"
                   TextWrapping="Wrap" MaxWidth="150"
                   TextAlignment="Center"/>
        <TextBlock Text="Height:"/>
        <TextBox Text="{Binding Path=CylinderHeight}"/>
        <TextBlock Text="Radius:"/>
        <TextBox Text="{Binding Path=CylinderRadius}"/>
        <TextBlock Text="Divisions:"/>
        <TextBox Text="{Binding Path=CylinderDivisions}"/>
        <Button Margin="5,10" Click="ClickButton">
            Draw Cylinder
        </Button>
    </StackPanel>
    <Canvas Name="Canvas1" Grid.Column="1">
        <Canvas.Background>
            <LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
                <GradientStop Color="#FFE2C98B" Offset="0" />
                <GradientStop Color="#FFFCEED2" Offset="1" />
            </LinearGradientBrush>
        </Canvas.Background>
            
    </Canvas>
</Grid>

您会注意到在上面的 XAML 中,唯一带有名称的控件是 Canvas,因为当单击“绘制圆柱体”按钮时,该控件会传递到另一个类。这演示了 WPF 的一个不错的特性。即使绑定到数据的文本框也不需要显式名称。

数据绑定非常基本,只是将 3 个文本框的 Text 属性绑定到 DrawingClass 类的相应属性。为了完成数据绑定,窗口的构造函数实例化了 DrawingClass 的一个新实例,并将其作为窗口的数据上下文(如下所示)

public DrawingClass dc;

public MainWindow()
{
    InitializeComponent();
    dc = new DrawingClass();
    this.DataContext = dc;
} 

下面是用于绘制圆柱体形状和代表圆柱体底部的弧线的代码片段。Canvas 对象传递给这个子例程,以便可以将各种几何图形直接添加到它上面。

public void DrawCylinder(System.Windows.Controls.Canvas cnv)
        {
            //Clear the existing children from the canvas.
            cnv.Children.Clear();

圆柱体顶部宽度与其高度的比例任意设置为 0.3,以便给人一种从圆柱体上方略微观看圆柱体的 3D 印象。

然后计算描述圆柱体对象的 4 个点,以及一个 ptC 点,它是构成圆柱体顶部表面的椭圆的中心。

int ellipseHeight = Convert.ToInt32( Math.Floor(cylinderRadius * 0.3));
Point ptUpperLeft = new Point(30, ellipseHeight*2);
Point ptUpperRight = new Point(30 + (cylinderRadius * 2), ptUpperLeft.Y);
Point ptLowerLeft = new Point(30, ptUpperLeft.Y + cylinderHeight);
Point ptLowerRight = new Point(ptUpperLeft.X + 
	(cylinderRadius * 2), ptUpperLeft.Y + cylinderHeight);
Point ptC = new Point(30 + cylinderRadius,ptUpperLeft.Y);

创建一个新的 Path 对象,该对象将包含各种 GeometryPathFigure Segments。然后将此路径添加到 Canvas。代码的其余部分未在此处显示,但使用类似的技术将其余图形添加到 Canvas

Path pth = new Path();
//Draw cylinder body.
LineSegment ln = new LineSegment(ptLowerLeft,true);
ArcSegment arc = new ArcSegment(ptLowerRight,new Size(cylinderRadius,ellipseHeight),
	0,false,System.Windows.Media.SweepDirection.Counterclockwise,true);
            
PathFigure pf = new PathFigure();
pf.StartPoint = ptUpperLeft;
//Add left side of cylinder.
pf.Segments.Add(ln);
//Add bottom arc of cylinder.
pf.Segments.Add(arc);
ln = new LineSegment(ptUpperRight,true);
//Add right side of cylinder.
pf.Segments.Add(ln);
PathGeometry pg = new PathGeometry();
pg.Figures.Add(pf);
pth.Stroke = new SolidColorBrush(Colors.Black);
pth.StrokeThickness = 2;
pth.Fill = new SolidColorBrush(Colors.White);
pth.Data = pg;
//Add path to the canvas.
cnv.Children.Add(pth);

关注点

在绘制弧线时,最简单的对象是 ArcSegment 对象。简单的线条可以同样容易地用 LineGeometryLineSegment 对象表示。最容易绘制完整的椭圆的是使用 EllipseGeometry 对象。

历史

  • 2012 年 1 月 27 日:初始发布
© . All rights reserved.