Why does this work correctly
My actual working code :
using Rhino;
using Rhino.Geometry;
using Rhino.DocObjects;
using System;
using System.IO;
using Rhino.FileIO;
namespace HelloRhinoCompute
{
public static class Convert3dm
{
public static string ConvertToStl(string data, bool exportAsBinary = true)
{
try
{
var decodedData = Convert.FromBase64String(data);
var file3dm = File3dm.FromByteArray(decodedData);
// Create a new document for exporting
using (var exportDoc = RhinoDoc.CreateHeadless(null))
{
// Add all objects to the export document
foreach (var obj in file3dm.Objects)
{
var geometry = obj.Geometry;
var attributes = obj.Attributes;
exportDoc.Objects.Add(geometry, attributes);
}
// Define the STL export options
var stlOptions = new FileStlWriteOptions
{
BinaryFile = exportAsBinary,
ExportOpenObjects = true,
MeshingParameters = MeshingParameters.Default
};
// Export to STL
var id = Guid.NewGuid();
string path = Path.GetTempPath();
string filename = Path.Combine(path, $"convert3dm_{id}.stl");
if (!FileStl.Write(filename, exportDoc, stlOptions))
{
throw new InvalidOperationException("STL export failed");
}
byte[] bytes = File.ReadAllBytes(filename);
// Clean up the temporary file
File.Delete(filename);
return Convert.ToBase64String(bytes);
}
}
catch (Exception ex)
{
throw new InvalidOperationException($"Error in ConvertToStl: {ex.Message}", ex);
}
}
}
}
My attempt at adding a layer filtering mechanism for model conversion, here it breaks. Need help here :
using Rhino;
using Rhino.Geometry;
using Rhino.DocObjects;
using System;
using System.IO;
using Rhino.FileIO;
namespace HelloRhinoCompute
{
public static class Convert3dm
{
public static string ConvertToStl(string data, bool exportAsBinary = true)
{
try
{
var decodedData = Convert.FromBase64String(data);
var file3dm = File3dm.FromByteArray(decodedData);
// Create a new document for exporting
using (var exportDoc = RhinoDoc.CreateHeadless(null))
{
// Add all objects to the export document
foreach (var obj in file3dm.Objects)
{
var geometry = obj.Geometry;
var attributes = obj.Attributes;
exportDoc.Objects.Add(geometry, attributes);
}
// Define the STL export options
var stlOptions = new FileStlWriteOptions
{
BinaryFile = exportAsBinary,
ExportOpenObjects = true,
MeshingParameters = MeshingParameters.Default
};
// Export to STL
var id = Guid.NewGuid();
string path = Path.GetTempPath();
string filename = Path.Combine(path, $"convert3dm_{id}.stl");
if (!FileStl.Write(filename, exportDoc, stlOptions))
{
throw new InvalidOperationException("STL export failed");
}
byte[] bytes = File.ReadAllBytes(filename);
// Clean up the temporary file
File.Delete(filename);
return Convert.ToBase64String(bytes);
}
}
catch (Exception ex)
{
throw new InvalidOperationException($"Error in ConvertToStl: {ex.Message}", ex);
}
}
// You can add other conversion methods (e.g., Convert3dmToPdf, Convert3dmToDwg) here if needed
}
}
I have this plugin on my local PC that works just fine (compiled as a plugin, not rhinocompute plugin), I need to make it into a RhinoCompute endpoint however I’m having a hard time understanding why the #2 code snippet I sent doesnt work, but the 1 does work correctly.
using Rhino;
using Rhino.Commands;
using Rhino.Geometry;
using Rhino.Input.Custom;
using Rhino.DocObjects;
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using Newtonsoft.Json.Linq;
using Rhino.FileIO;
public class ExportMetalObjectsOnly : Command
{
public override string EnglishName => "ExportMetalObjectsOnly";
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
RhinoApp.WriteLine("Starting ExportMetalObjectsOnly command...");
try
{
// Prompt the user to select objects
var go = new GetObject
{
GroupSelect = true,
SubObjectSelect = false
};
go.SetCommandPrompt("Select objects to export to STL");
go.GetMultiple(1, 0);
if (go.CommandResult() != Result.Success)
{
RhinoApp.WriteLine("Object selection failed or was cancelled.");
return go.CommandResult();
}
var objectsToExport = go.Objects();
// Check if any objects were selected
if (objectsToExport.Length == 0)
{
RhinoApp.WriteLine("No objects selected. Exiting command.");
return Result.Failure;
}
RhinoApp.WriteLine($"Selected {objectsToExport.Length} objects for export.");
// Create a new document for exporting
using (var exportDoc = RhinoDoc.CreateHeadless(null))
{
RhinoApp.WriteLine("Created headless document for export.");
// Loop through selected objects and remove non-metal (gem) objects
foreach (var objRef in objectsToExport)
{
var geometry = objRef.Geometry();
var attributes = objRef.Object().Attributes;
string layerName = doc.Layers[attributes.LayerIndex].Name;
RhinoApp.WriteLine($"Processing object on layer: {layerName}");
// Classify the layer name using LLAMA model
bool isMetal = ClassifyMaterial(layerName);
if (isMetal)
{
// Add the metal object to the export document
var newAttributes = attributes.Duplicate();
exportDoc.Objects.Add(geometry, newAttributes);
RhinoApp.WriteLine("Object added to export document (metal).");
}
else
{
RhinoApp.WriteLine("Object skipped (gem).");
}
// Ensure API requests are limited to 1 per second
Thread.Sleep(1000); // 1 second delay
}
// Define the STL export options
var stlOptions = new FileStlWriteOptions
{
BinaryFile = true,
ExportOpenObjects = true,
MeshingParameters = MeshingParameters.Default
};
// Define the destination path on the desktop
var desktopPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop);
var exportFilePath = Path.Combine(desktopPath, "ExportedMetalObjects.stl");
RhinoApp.WriteLine($"Preparing to export to: {exportFilePath}");
// Export to STL
bool success = FileStl.Write(exportFilePath, exportDoc, stlOptions);
if (success)
{
RhinoApp.WriteLine($"Successfully exported to {exportFilePath}");
return Result.Success;
}
else
{
RhinoApp.WriteLine("Failed to export STL file.");
return Result.Failure;
}
}
}
catch (Exception ex)
{
RhinoApp.WriteLine($"An error occurred: {ex.Message}");
RhinoApp.WriteLine($"Stack trace: {ex.StackTrace}");
return Result.Failure;
}
}
private static bool ClassifyMaterial(string layerName)
{
string apiKey = "xx";
string apiUrl = "https://api.together.xyz/v1/chat/completions";
try
{
RhinoApp.WriteLine($"Classifying material by layer name: {layerName}");
var request = (HttpWebRequest)WebRequest.Create(apiUrl);
request.Method = "POST";
request.ContentType = "application/json";
request.Headers.Add("Authorization", $"Bearer {apiKey}");
var requestBody = new
{
model = "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
messages = new[]
{
new { role = "system", content = "You are a helpful assistant that classifies materials as either metal or gem. Respond with 1 for metal or 0 for gem." },
new { role = "user", content = $"Is the material represented by the layer name '{layerName}' a metal or a gem? Respond with 1 for metal or 0 for gem." }
},
max_tokens = 10,
temperature = 0.7,
top_p = 0.7,
top_k = 50,
repetition_penalty = 1,
stop = new[] { "<|eot_id|>", "<|eom_id|>" }
};
string jsonRequest = Newtonsoft.Json.JsonConvert.SerializeObject(requestBody);
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(jsonRequest);
}
using (var response = (HttpWebResponse)request.GetResponse())
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
string responseBody = streamReader.ReadToEnd();
RhinoApp.WriteLine($"API Response: {responseBody}");
var jsonResponse = JObject.Parse(responseBody);
string assistantResponse = jsonResponse["choices"][0]["message"]["content"].ToString().Trim();
bool isMetal = assistantResponse == "1";
RhinoApp.WriteLine($"Classification result: {(isMetal ? "Metal" : "Gem")}");
return isMetal;
}
}
catch (WebException ex)
{
using (var streamReader = new StreamReader(ex.Response.GetResponseStream()))
{
string errorResponse = streamReader.ReadToEnd();
RhinoApp.WriteLine($"API Error: {errorResponse}");
}
RhinoApp.WriteLine($"WebException occurred in ClassifyMaterial: {ex.Message}");
return true; // Default to metal if classification fails
}
catch (Exception ex)
{
RhinoApp.WriteLine($"Error in ClassifyMaterial: {ex.Message}");
return true; // Default to metal if classification fails
}
}
}
I need to make this plugin work as a endpoint basically…
Could I get some help?
Thank you guys