从通用 Windows 平台应用中打印 3D
了解如何将 3D 打印功能添加到 通用 Windows 平台 (UWP) 应用。
本主题介绍如何将 3D 几何数据加载到应用中,并在确保 3D 模型可打印且格式正确后启动 3D 打印对话框。 有关这些过程的工作示例,请参阅 3D 打印 UWP 示例。
重要的 API
安装
将 Windows.Graphics.Printing3D 命名空间添加到需要 3D 打印功能的应用程序类。
using Windows.Graphics.Printing3D;
本指南中还将使用以下命名空间。
using System;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
接下来,为类提供有用的成员字段。
- 声明一个 Print3DTask 对象,表示要传递给打印驱动程序的打印任务。
- 声明一个 StorageFile 对象以保存将加载到应用中的原始 3D 数据文件。
- 声明 Printing3D3MFPackage 对象以表示具有所有必要元数据的打印就绪 3D 模型。
private Print3DTask printTask;
private StorageFile file;
private Printing3D3MFPackage package = new Printing3D3MFPackage();
创建简单的 UI
此示例使用“加载”按钮将文件引入程序内存,使用“修复”按钮对文件进行任何所需的修改,以及启动打印作业的“打印”按钮。 以下代码在.cs类的相应 XAML 文件中创建这些按钮(其单击事件处理程序)。
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<Button x:Name="loadbutton" Content="Load Model from File" HorizontalAlignment="Center" Margin="5,5,5,5" VerticalAlignment="Center" Click="OnLoadClick"/>
<Button x:Name="fixbutton" Content="Fix Model" HorizontalAlignment="Center" Margin="5,5,5,5" VerticalAlignment="Center" Click="OnFixClick"/>
<Button x:Name="printbutton" Content="Print" HorizontalAlignment="center" Margin="5,5,5,5" VerticalAlignment="Center" Click="OnPrintClick"/>
此示例还包括 用于 UI 反馈的 TextBlock 。
<TextBlock x:Name="OutputTextBlock" TextAlignment="Center"></TextBlock>
</StackPanel>
获取 3D 数据
应用获取 3D 几何数据的方法可能有所不同。 应用可以从 3D 扫描中检索数据、从 Web 资源下载模型数据,或使用数学公式或用户输入以编程方式生成 3D 网格。 在这里,我们将演示如何将 3D 数据文件(其中任意一种常见文件类型)从设备存储加载到程序内存中。 3D Builder 模型库提供了各种模型供你下载。
在 OnLoadClick
方法中 ,FileOpenPicker 类将单个文件加载到应用内存中。
以下代码演示如何在方法中使用 FileOpenPicker 类将单个文件加载到应用内存中OnLoadClick
。
private async void OnLoadClick(object sender, RoutedEventArgs e) {
FileOpenPicker openPicker = new FileOpenPicker();
// allow common 3D data file types
openPicker.FileTypeFilter.Add(".3mf");
openPicker.FileTypeFilter.Add(".stl");
openPicker.FileTypeFilter.Add(".ply");
openPicker.FileTypeFilter.Add(".obj");
// pick a file and assign it to this class' 'file' member
file = await openPicker.PickSingleFileAsync();
if (file == null) {
return;
}
使用 3D Builder 转换为 3D 制造格式 (.3mf)
3D 几何图形数据可以采用多种不同的格式,并非所有数据对 3D 打印都有效。 Windows 对所有 3D 打印任务使用 3D 制造格式 (.3mf) 文件类型。
请参阅 3MF 规范,详细了解 3MF 以及 3D 产品的生产者和使用者支持的功能。 若要了解如何通过 Windows API 利用这些功能,请参阅“ 生成 3MF 包 ”教程。
注意
3D Builder 应用可以打开最常用的 3D 格式的文件,并将其另存为 .3mf 文件。 它还提供用于编辑模型、添加颜色数据以及执行其他特定于打印的操作的工具。
在此示例中,文件类型可能有所不同,可以打开 3D Builder 应用并提示用户将导入的数据另存为 .3mf 文件,然后重新加载它。
// if user loaded a non-3mf file type
if (file.FileType != ".3mf") {
// elect 3D Builder as the application to launch
LauncherOptions options = new LauncherOptions();
options.TargetApplicationPackageFamilyName = "Microsoft.3DBuilder_8wekyb3d8bbwe";
// Launch the retrieved file in 3D builder
bool success = await Windows.System.Launcher.LaunchFileAsync(file, options);
// prompt the user to save as .3mf
OutputTextBlock.Text = "save " + file.Name + " as a .3mf file and reload.";
// have user choose another file (ideally the newly-saved .3mf file)
file = await openPicker.PickSingleFileAsync();
} else {
// if the file type is .3mf
// notify user that load was successful
OutputTextBlock.Text = file.Name + " loaded as file";
}
}
修复 3D 打印的模型数据
并非所有 3D 模型数据都可以打印,即使在 .3mf 类型中也是如此。 为了使打印机正确确定要填充的空间以及要留空的空间,要打印的每个模型必须是一个无缝网格,具有向外表面法线,并且具有人造几何图形。 这些领域的问题可能以各种不同形式出现,在复杂的形状中很难发现。 但是,新式软件解决方案通常足以将原始几何图形转换为可打印的 3D 形状。 这称为 修复 模型,并在此处所示的方法中 OnFixClick
实现。
注意
必须将 3D 数据文件转换为实现 IRandomAccessStream,然后可以使用该文件生成 Printing3DModel 对象。
private async void OnFixClick(object sender, RoutedEventArgs e) {
// read the loaded file's data as a data stream
IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read);
// assign a Printing3DModel to this data stream
Printing3DModel model = await package.LoadModelFromPackageAsync(fileStream);
// use Printing3DModel's repair function
OutputTextBlock.Text = "repairing model";
var data = model.RepairAsync();
Print3DModel 对象现在应修复并可打印。 使用 SaveModelToPackageAsync 将模型分配给创建类时声明的 Printing3D3MFPackage 对象。
// save model to this class' Printing3D3MFPackage
OutputTextBlock.Text = "saving model to 3MF package";
await package.SaveModelToPackageAsync(model);
}
执行打印任务:创建 TaskRequested 处理程序
稍后,当用户显示 3D 打印对话框并且用户选择开始打印时,你的应用需要将所需参数传递到 3D 打印管道。 3D 打印 API 将引发 TaskRequested 事件,这需要适当处理。
private void MyTaskRequested(Print3DManager sender, Print3DTaskRequestedEventArgs args) {
此方法的核心用途是使用 args 参数将 Printing3D3MFPackage 发送到管道。 Print3DTaskRequestedEventArgs 类型有一个属性:请求。 它的类型为 Print3DTaskRequest ,表示一个打印作业请求。 其方法 CreateTask 允许应用提交打印作业的正确信息,并返回对 3D 打印管道中发送的 Print3DTask 对象的引用。
CreateTask 具有以下输入参数:打印作业名称的字符串、要使用的打印机 ID 的字符串,以及 Print3DTaskSourceRequestedHandler 委托。 引发 3DTaskSourceRequested 事件时,会自动调用委托(这是由 API 本身完成的)。 需要注意的一点是,启动打印作业时会调用此委托,并负责提供正确的 3D 打印包。
Print3DTaskSourceRequestedHandler 采用一个 参数 Print3DTaskSourceRequestedArgs 对象,其中包含要发送的数据。 SetSource 方法接受要打印的包。 以下代码显示了 Print3DTaskSourceRequestedHandler 委托实现(sourceHandler
)。
// this delegate handles the API's request for a source package
Print3DTaskSourceRequestedHandler sourceHandler = delegate (Print3DTaskSourceRequestedArgs sourceRequestedArgs) {
sourceRequestedArgs.SetSource(package);
};
接下来,使用新定义的委托调用 CreateTask。
// the Print3DTaskRequest ('Request'), a member of 'args', creates a Print3DTask to be sent down the pipeline.
printTask = args.Request.CreateTask("Print Title", "Default", sourceHandler);
返回的 Print3DTask 分配给在开头声明的类变量。 此引用可用于处理任务引发的某些事件。
// optional events to handle
printTask.Completed += Task_Completed;
printTask.Submitting += Task_Submitting;
注意
如果要将这些事件注册到这些事件,则必须实现一个 Task_Submitting
和 Task_Completed
方法。
执行打印任务:打开 3D 打印对话框
最后,需要启动提供许多打印选项的 3D 打印对话框。
在这里,我们将方法注册 MyTaskRequested
到 TaskRequested 事件。
private async void OnPrintClick(object sender, RoutedEventArgs e) {
// get a reference to this class' Print3DManager
Print3DManager myManager = Print3DManager.GetForCurrentView();
// register the method 'MyTaskRequested' to the Print3DManager's TaskRequested event
myManager.TaskRequested += MyTaskRequested;
注册 TaskRequested 事件处理程序后,可以调用 ShowPrintUIAsync 方法,该方法将在当前应用程序窗口中显示 3D 打印对话框。
// show the 3D print dialog
OutputTextBlock.Text = "opening print dialog";
var result = await Print3DManager.ShowPrintUIAsync();
在应用恢复控制后,最好取消注册事件处理程序。
// remove the print task request after dialog is shown
myManager.TaskRequested -= MyTaskRequested;
}