I need to read the transform matrix of block instances with specific names in up to 26000 rhino files…
I have successfully manage to read transform matrix previously, is a DOC… but… read as a FILE3DM its not working…
While I can access the InstanceDefintions which returns a format InstanceDefintionGeometry, which oddly I can scale, transform and translate, however I cannot actually read the current transform information back from an existing file…
Any leads, I really don’t want to sit opening 26000 files
QUASICODE:
GetDirectory
new List(all files that end in .3dm)
iterate List {
AA = File3DM.read(next file)
var instancelists = AA.Instancedefinitions
iterate each instance{
if instance.name = “somename” then Transform XXX = instance.blockinstanceXform
Yes, I know, thats the question… it does not exist in the list of things that can be read, without actually opening the file in rhino into a DOC… I can do this fine with a file open in rhino, Im needing to do it without actually having to load 26000 files one at a time into rhino.
@dale , what am I missing here, is there a way to read the transform matrix without loading the file into rhino?
Basically there is no table for all instanceReferences, even if you were to open the file, so the only way is to iterate over all objects and look if they are instances of your wanted instanceDefinition.
For those wanting the Python equivalent, here you go:
import Rhino
import clr
filename = ...
with Rhino.FileIO.File3dm.Read(filename) as f:
for rhobj in f.Objects:
if type(rhobj.Geometry) is Rhino.Geometry.InstanceReferenceGeometry:
iref = clr.Convert(rhobj.Geometry, Rhino.Geometry.InstanceReferenceGeometry)
xform = iref.Xform
print xform
Using below I am 99% of where i need to be, what I seem to be unable to extract is the name of the block instance, inside of the objectloop (I can extract the scale info no problem, but iref NAME returns the object name, not the name of the blockinstance?
A secondary goal (id like but not critical) would be to extract the volume of the geometry inside the blockinstance, in my case always only one polysrf.)
(thank you for the post of how to deconvolute a transform array, super helpful!)
private void Scrubber()
{
using (var GetFolder = new FolderBrowserDialog())
{
string ConcatString = "";
DialogResult result = GetFolder.ShowDialog();
if (result == DialogResult.OK)
{
DirectoryInfo d = new DirectoryInfo(GetFolder.SelectedPath);
Files = d.GetFiles("*.3dm").ToList();
foreach (FileInfo file in Files)
{
using (var CurrentFile = File3dm.Read(file.FullName))
{
ConcatString += file.Name + ", ";
foreach (var obj in CurrentFile.Objects)
{
if (obj.Name.Contains("Ring Rail")){ ConcatString += obj.Name + ", ";}
//retrieving instance name here retrives the high level name, not the blockinstance name itself
//ie: Object Name = Brick
//actiual instance name inside that object is SquareBrick, I need SquareBrick.
if (obj.Geometry is InstanceReferenceGeometry iref)
{
var xform = iref.Xform;
//we only need XScale for now, leaving rest in for next coder "just in case"
// rest at https://github.com/mcneel/rhino-developer-samples/blob/master/rhinoscript/DecomposeXform.rvb
var XScale = Math.Sqrt((Math.Pow(xform.M00,2.0)) + (Math.Pow(xform.M01, 2.0)) + (Math.Pow(xform.M02, 2.0)));
var YScale = Math.Sqrt((Math.Pow(xform.M10, 2.0)) + (Math.Pow(xform.M11, 2.0)) + (Math.Pow(xform.M12, 2.0)));
var ZScale = Math.Sqrt((Math.Pow(xform.M20, 2.0)) + (Math.Pow(xform.M21, 2.0)) + (Math.Pow(xform.M22, 2.0)));
var XLocation = xform.M03; var YLocation = xform.M03; var ZLocation = xform.M03;
var XRotate = Math.Atan2(-xform.M21, xform.M22);
var YRotate = Math.Asin(xform.M20);
var ZRotate = Math.Atan2(xform.M10, xform.M00);
//stuck at retrieving the instance name in this loop.
ConcatString += XScale.ToString("0.##") + "mm, ";
}
}
ConcatString += Environment.NewLine;
}
RhinoApp.WriteLine(ConcatString);
}
}
}
If you are at a loose end, see my second question re extraction the volume of that polysurface in the block instance, its only of academic interest as I already know the volume before it was scaled, and ergo can formulate the volume multiplied by the scaling , however would be interesting to see the code to extract it directly from the polysrf itself in that instance (in my case its a rectangle so formula would be right, but if it was a non linear object, im guessing no formula for multiplying scale on a volume would be accurate.)
After you get the InstanceDefinitionGeometry object, you can get the ids of the definition geometry using InstanceDefinitionGeometry.GetObjectIds. Lookup these objects in the object table, or File3dm.Objects. When found, make a copy of the geometry and then transform it with the Transform you obtained prior. Then make your mass properties calculation.
@dale, thank you that worked, the gem scraper is done collecting 15000 files already!
another question if I may. this is one half of the thing I’m building, my problem now is after I complete stages below, I am left with nice clean, sealed, booleaned meshes in a
List(Mesh), (without affecting anything in the document, just in memory) and I need to save out each List(Mesh) as its own STL file.Pointers would be most appreciated!