Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add view capturing capability #230

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions Rhinoceros_Engine/Compute/CaptureNamedViews.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.oM.Base;
using BH.oM.Base.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.IO;
using Rhino;
using Rhino.Display;
using System.Drawing;
using BH.oM.Rhinoceros.ViewCapture;
using System.Drawing.Imaging;

namespace BH.Engine.Rhinoceros
{
public static partial class Compute
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Captures all named views to files.")]
[Input("active", "Toggle to activate. Toggle to true to capture the view port.")]
[Input("folderPath", "Folder path to store the image in. To folder that the currently open rhino model is stored in will be used if nothing is provided.")]
[Input("imageName", "Name of the image, without file ending. THe name of the image will be this name + _viewName. To update the file ending, please see the viewcapture settings. If nothing is provided, the named view name will be the full filename.")]
[Input("namedViewFilter", "Optional filter of which named views that should be captured to file. All named views are captured if nothing is provided.")]
[Input("settings", "Settings to control the view capture.")]
[Output("success", "Returns true if the view capture was successful.")]
public static bool CaptureNamedViews(bool active = false, string folderPath = "", string imageName = "", List<string> namedViewFilter = null, IViewCaptureSettings settings = null)
{
RhinoDoc doc = RhinoDoc.ActiveDoc;

folderPath = ValidateFolderPath(folderPath, doc);
if (folderPath == null)
return false;

if (!active)
return false;

bool success = true;

settings = settings ?? new ScaleViewCaptureSettings(); //Default view capture settings

for (int i = 0; i < doc.NamedViews.Count; i++)
{
string namedView = doc.NamedViews[i].Name;

if (namedViewFilter != null && namedViewFilter.Count != 0) //If named view filter provided
if (!namedViewFilter.Contains(namedView)) //Filter out items in the list. If no filter provided, assume all to be captured
continue;

doc.NamedViews.Restore(i, doc.Views.ActiveView.ActiveViewport);
string name;
if (string.IsNullOrEmpty(imageName))
name = namedView;
else
name = imageName + "_" + namedView;
success &= CaptureActiveView(doc, settings, folderPath, name);

}

return success;
}

/***************************************************/
}
}
205 changes: 205 additions & 0 deletions Rhinoceros_Engine/Compute/CaptureView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, the respective contributors. All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
*
* The BHoM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3.0 of the License, or
* (at your option) any later version.
*
* The BHoM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.oM.Base;
using BH.oM.Base.Attributes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.IO;
using Rhino;
using Rhino.Display;
using System.Drawing;
using BH.oM.Rhinoceros.ViewCapture;
using System.Drawing.Imaging;

namespace BH.Engine.Rhinoceros
{
public static partial class Compute
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Captures the currently active view to file.")]
[Input("active", "Toggle to activate. Toggle to true to capture the view port.")]
[Input("folderPath", "Folder path to store the image in. To folder that the currently open rhino model is stored in will be used if nothing is provided.")]
[Input("imageName", "Name of the image, without file ending. To update the file ending, please see the viewcapture settings. The viewport name will be used if nothing is provided.")]
[Input("settings", "Settings to control the view capture.")]
[Output("success", "Returns true if the view capture was successful.")]
public static bool CaptureView(bool active = false, string folderPath = "", string imageName = "", IViewCaptureSettings settings = null)
{
RhinoDoc doc = Rhino.RhinoDoc.ActiveDoc;

folderPath = ValidateFolderPath(folderPath, doc);
if (folderPath == null)
return false;

if (!active)
return false;

settings = settings ?? new ScaleViewCaptureSettings(); //Default view capture settings

return CaptureActiveView(doc, settings, folderPath, imageName);
}


/***************************************************/
/**** Private Methods ****/
/***************************************************/

[Description("")]
[Input("", "")]
[Output("", "")]
private static bool CaptureActiveView(RhinoDoc doc, IViewCaptureSettings settings, string folderName, string imageName)
{
var view = doc.Views.ActiveView;

if (string.IsNullOrWhiteSpace(imageName))
{
Engine.Base.Compute.RecordNote("No image name provided. Name of active viewport will be used.");
imageName = view.ActiveViewport.Name;
}

ViewCapture viewCapture = settings.IViewCapture(view.ActiveViewport);

if (viewCapture == null)
return false;

var bitmap = viewCapture.CaptureToBitmap(view);

if (null != bitmap)
{
string fileEnding;
ImageFormat imageFormat = settings.GetImageFormat(out fileEnding);
if (imageFormat == null)
return false;

var filename = Path.Combine(folderName, imageName + fileEnding);
bitmap.Save(filename, imageFormat);
return true;
}

return false;
}

/***************************************************/

private static string ValidateFolderPath(string folderPath, RhinoDoc doc)
{
if (string.IsNullOrEmpty(folderPath))
{
folderPath = Path.GetDirectoryName(doc.Path);
Engine.Base.Compute.RecordNote($"No path provided. Images will be saved in the same folder as the Open rhino model.");
}

if (!Directory.Exists(folderPath))
{
Engine.Base.Compute.RecordError($"Directory {folderPath} does not exist.");
return null;
}
return folderPath;
}

/***************************************************/

private static ImageFormat GetImageFormat(this IViewCaptureSettings settings, out string fileEnding)
{
string imageFormat = settings.FileFormat.ToUpper();

switch (imageFormat)
{
case "BMP":
fileEnding = ".bmp";
return ImageFormat.Bmp;
case "EMF":
fileEnding = ".emf";
return ImageFormat.Emf;
case "WMF":
fileEnding = ".wmf";
return ImageFormat.Wmf;
case "GIF":
fileEnding = ".gif";
return ImageFormat.Gif;
case "JPG":
case "JPEG":
fileEnding = ".jpg";
return ImageFormat.Jpeg;
case "PNG":
fileEnding = ".png";
return ImageFormat.Png;
case "TIFF":
fileEnding = ".tiff";
return ImageFormat.Tiff;
case "EXIF":
fileEnding = ".exif";
return ImageFormat.Exif;
case "ICON":
fileEnding = ".icon";
return ImageFormat.Icon;
default:
Engine.Base.Compute.RecordError("Unknown image format.");
fileEnding = "";
return null;
}
}

/***************************************************/

private static ViewCapture IViewCapture(this IViewCaptureSettings settings, RhinoViewport viewport)
{
ViewCapture viewCapture = ViewCapture(settings as dynamic, viewport);
viewCapture.ScaleScreenItems = settings.ScaleScreenItems;
viewCapture.DrawAxes = settings.DrawAxes;
viewCapture.DrawGrid = settings.DrawGrid;
viewCapture.DrawGridAxes = settings.DrawGridAxes;
viewCapture.TransparentBackground = settings.TransparentBackground;
viewCapture.Preview = settings.Preview;
return viewCapture;
}

/***************************************************/

private static ViewCapture ViewCapture(this ScaleViewCaptureSettings settings, RhinoViewport viewport)
{
return new ViewCapture
{
Height = (int)Math.Round(viewport.Size.Height * settings.Scale),
Width = (int)Math.Round(viewport.Size.Width * settings.Scale)
};
}

/***************************************************/

private static ViewCapture ViewCapture(this DimensionViewCaptureSettings settings, RhinoViewport viewport)
{
return new ViewCapture
{
Height = settings.Height,
Width = settings.Width
};
}

/***************************************************/
}
}
29 changes: 21 additions & 8 deletions Rhinoceros_Engine/Rhinoceros_Engine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
<HintPath>C:\ProgramData\BHoM\Assemblies\Dimensional_oM.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Eto, Version=2.5.0.0, Culture=neutral, PublicKeyToken=552281e97c755530, processorArchitecture=MSIL">
<HintPath>..\packages\RhinoCommon.6.33.20343.16431\lib\net45\Eto.dll</HintPath>
</Reference>
<Reference Include="Geometry_Engine">
<HintPath>C:\ProgramData\BHoM\Assemblies\Geometry_Engine.dll</HintPath>
<Private>False</Private>
Expand All @@ -62,9 +65,11 @@
<HintPath>C:\ProgramData\BHoM\Assemblies\Graphics_oM.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RhinoCommon, Version=5.1.30000.16, Culture=neutral, PublicKeyToken=552281e97c755530, processorArchitecture=MSIL">
<HintPath>..\packages\RhinoCommon.5.12.50810.13095\lib\net35\RhinoCommon.dll</HintPath>
<Private>True</Private>
<Reference Include="Rhino.UI, Version=6.33.20343.16430, Culture=neutral, PublicKeyToken=552281e97c755530, processorArchitecture=MSIL">
<HintPath>..\packages\RhinoCommon.6.33.20343.16431\lib\net45\Rhino.UI.dll</HintPath>
</Reference>
<Reference Include="RhinoCommon, Version=6.33.20343.16430, Culture=neutral, PublicKeyToken=552281e97c755530, processorArchitecture=MSIL">
<HintPath>..\packages\RhinoCommon.6.33.20343.16431\lib\net45\RhinoCommon.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
Expand All @@ -77,6 +82,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Compute\CaptureNamedViews.cs" />
<Compile Include="Compute\CaptureView.cs" />
<Compile Include="Convert\FromRhino.cs" />
<Compile Include="Convert\ToRhino.cs" />
<Compile Include="Convert\ToRhino5.cs" />
Expand Down Expand Up @@ -108,17 +115,23 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Rhinoceros_oM\Rhinoceros_oM.csproj">
<Project>{5c0492bc-0ff4-45c9-963c-2514add35263}</Project>
<Name>Rhinoceros_oM</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\RhinoCommon.5.12.50810.13095\build\net35\RhinoCommon.targets" Condition="Exists('..\packages\RhinoCommon.5.12.50810.13095\build\net35\RhinoCommon.targets')" />
<PropertyGroup>
<PostBuildEvent>xcopy "$(TargetDir)$(TargetFileName)" "C:\\ProgramData\\BHoM\\Assemblies" /Y</PostBuildEvent>
</PropertyGroup>
<Import Project="..\packages\RhinoCommon.6.33.20343.16431\build\net45\RhinoCommon.targets" Condition="Exists('..\packages\RhinoCommon.6.33.20343.16431\build\net45\RhinoCommon.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\RhinoCommon.5.12.50810.13095\build\net35\RhinoCommon.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RhinoCommon.5.12.50810.13095\build\net35\RhinoCommon.targets'))" />
<Error Condition="!Exists('..\packages\RhinoCommon.6.33.20343.16431\build\net45\RhinoCommon.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\RhinoCommon.6.33.20343.16431\build\net45\RhinoCommon.targets'))" />
</Target>
<PropertyGroup>
<PostBuildEvent>xcopy "$(TargetDir)$(TargetFileName)" "C:\\ProgramData\\BHoM\\Assemblies" /Y</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
2 changes: 1 addition & 1 deletion Rhinoceros_Engine/packages.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="RhinoCommon" version="5.12.50810.13095" targetFramework="net452" />
<package id="RhinoCommon" version="6.33.20343.16431" targetFramework="net472" />
michaelhoehn marked this conversation as resolved.
Show resolved Hide resolved
</packages>
6 changes: 6 additions & 0 deletions Rhinoceros_Toolkit.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.29728.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhinoceros_Engine", "Rhinoceros_Engine\Rhinoceros_Engine.csproj", "{93CEDC69-F9C0-4E08-9E94-07F120D811DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rhinoceros_oM", "Rhinoceros_oM\Rhinoceros_oM.csproj", "{5C0492BC-0FF4-45C9-963C-2514ADD35263}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -15,6 +17,10 @@ Global
{93CEDC69-F9C0-4E08-9E94-07F120D811DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93CEDC69-F9C0-4E08-9E94-07F120D811DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93CEDC69-F9C0-4E08-9E94-07F120D811DC}.Release|Any CPU.Build.0 = Release|Any CPU
{5C0492BC-0FF4-45C9-963C-2514ADD35263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C0492BC-0FF4-45C9-963C-2514ADD35263}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C0492BC-0FF4-45C9-963C-2514ADD35263}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C0492BC-0FF4-45C9-963C-2514ADD35263}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading