Preview Image

Hi,

I’m attempting to create preview images of individual pieces of geometry. Based on other posts here, I think this should work, but it doesn’t:

using System;
using System.IO;
using System.Linq;
using Rhino;
using Rhino.Commands;
using Rhino.Display;

namespace Dev.Common
{
    [
        System.Runtime.InteropServices.Guid("e58debff-8f45-4a1c-8b12-32ed2fe44363"),
        CommandStyle(Style.ScriptRunner)
    ]
    public class DevCommand : Command
    {
        public DevCommand()
        {
            // Rhino only creates one instance of each command class defined in a
            // plug-in, so it is safe to store a refence in a static property.
            Instance = this;
        }

        ///<summary>The only instance of this command.</summary>
        public static DevCommand Instance { get; private set; }

        public override string EnglishName => "MyDevCommand";

        protected override Result RunCommand(Rhino.RhinoDoc doc, RunMode mode)
        {
            // Assumes at least one object is selected.
            var selectedId = doc.Objects.GetSelectedObjects(false, false).Select(o => o.Id).First();

            if (GenerateImage(selectedId, doc))
            {
                RhinoApp.WriteLine("Created image");
                return Result.Success;
            } else
            {
                RhinoApp.WriteLine("Failed creating image");
                return Result.Failure;
            }
        }

        private static bool GenerateImage(Guid guid, RhinoDoc doc)
        {
            try
            {
                // Create a new RhinoView
                RhinoView rhinoView = doc.Views.Add(
                    "Preview",
                    DefinedViewportProjection.Perspective,
                    new System.Drawing.Rectangle(0, 0, 512, 512),
                    true
                );

                // Get a tmp file path
                var filePath = Path.Combine(Path.GetTempFileName(), ".bmp");

                // Zoom Selected
                var zoomSuccess = rhinoView.MainViewport.ZoomExtentsSelected();

                // Make sure the view is updated..
                rhinoView.Redraw();

                // Save a preview image
                return rhinoView.CreateShadedPreviewImage(filePath, new System.Drawing.Size(512, 512), true, false, false);
            } finally
            {
                // Clean up the view
                var views = doc.Views.Where(v => v.MainViewport.Name == "Preview").ToList();
                foreach (var v in views)
                {
                    v.Close();
                }
            }
        }
    }
}

Can anyone spot what I am doing wrong here? I’ve tried with .jpeg, .png, and without extension as well. I’m on Mac, and Rhino 6.

Thanks,
Aske

Hi @aske,

See if this SDK sample is helpful:

SampleCsViewCapture.cs

– Dale

Hi @dale

Thanks! I already had looked and used that example but can’t get it to work properly. Also, hijacking the ActiveView seems dirty: what if it’s a Layout view? I guess I could restore the previous settings for normal views, but it still feels a bit iffy.

This is what I’ve tried:

        private static bool GenerateImage3(Guid guid, RhinoDoc doc)
        {
            // What if ActiveView is a Layout?
            RhinoView rhinoView = doc.Views.ActiveView;

            // Get a tmp file path
            var filePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.png");
            RhinoApp.WriteLine(filePath);
            // Zoom Selected
            var zoomSuccess = rhinoView.MainViewport.ZoomExtentsSelected();

            rhinoView.MainViewport.DisplayMode = DisplayModeDescription.GetDisplayMode(DisplayModeDescription.ShadedId);

            // Make sure the view is updated..
            rhinoView.Redraw();

            var view_capture = new ViewCapture
            {
                Width = rhinoView.ActiveViewport.Size.Width,
                Height = rhinoView.ActiveViewport.Size.Height,
                ScaleScreenItems = false,
                DrawAxes = false,
                DrawGrid = false,
                DrawGridAxes = false,
                TransparentBackground = true
            };

            var bitmap = view_capture.CaptureToBitmap(rhinoView);
            if (null != bitmap)
            {
                bitmap.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
                return true;
            }
            else
            {
                return false;
            }
        }

The shaded mode is not respected. It only changes after the command has run. On DetailViews there is a CommitViewportChanges method, but I can’t find anything similar on RhinoView. Is there anything I can do to force a view/viewport update?

Thanks,

I ended up giving up.
I wrote a glTF-binary exporter instead, and will use that for previews instead. That was easier than getting consistent results out of Rhino. I’m probably doing something wrong somewhere since it’s that hard.

Hi @aske,

The sample that I posted does work if the active view is a layout, or RhinoPageView, at least on Windows. Your using a Mac, right?

– Dale

I’m on a Mac yes.
The sample you posted works. Both on V6 and V7.