My ultimate goal is to be able to extract the Brep (polygonal cage) and Trim Curves so that I can reproduce them inside of Houdini for futher experimentation.
Before I get ahead of myself, I need to learn about various I/O approach in OpenNURBS.
I see that there are multiple ways to open a *.3dm file in OpenNURBS to look for information.
If I am mostly after Brep and Trim Curves, what is the recommended way to load a *.3dm via OpenNURBS ?
Now that I can find the Trim Curves and also which Brep it belongs to, I have further questions.
What coordinate space are the Trim Curves CVs in ? I see a lot of trim curves in the model I loaded as a test (Rhino logo 3dm), more than I expect. Some of the trim curves has only 2 CVs which looks suspicious to me. I don’t have a 1 Brep 1 Trim Curve *.3dm as a learning starting point so I am a little overwhelm with the data at the moment but making progress.
Does OpenNURBS use right or left handed coordinate system ?
#include <opennurbs_public.h>
#include <string>
#include <boost/format.hpp>
#include <iostream>
#include <cstdio>
int main(int argc, char **argv) {
if (argc != 2) {
std::cerr << boost::format("Usage: %1% <3dm file>") % argv[0] << std::endl;
return 1;
}
ON::Begin();
ON_TextLog error_log;
ONX_Model model;
std::string filename(argv[1]);
if (model.Read(filename.c_str()))
{
ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::ModelGeometry);
const ON_ModelComponent* model_component = nullptr;
for (model_component = it.FirstComponent(); nullptr != model_component; model_component = it.NextComponent())
{
const ON_ModelGeometryComponent* model_geometry = ON_ModelGeometryComponent::Cast(model_component);
if (nullptr != model_geometry)
{
// Test for Brep object
const ON_Brep* brep = ON_Brep::Cast(model_geometry->Geometry(nullptr));
if (nullptr != brep)
{
// TODO: do something with the Brep...
std::cout << "BREP" << std::endl;
// Surface
{
unsigned int num_surface = brep->m_S.Count();
std::cout << "num_surface = " << num_surface << std::endl;
for (auto s_index=0;s_index<num_surface;s_index++)
{
if (brep->m_S[s_index]->HasNurbForm())
{
ON_NurbsSurface nurbs_surface;
if (brep->m_S[s_index]->GetNurbForm(nurbs_surface))
{
int order0 = nurbs_surface.m_order[0];
int order1 = nurbs_surface.m_order[1];
std::cout << boost::format("order0=%1%, order1=%2%") % order0 % order1 << std::endl;
}
}
}
}
// Trim
{
unsigned int num_trim = brep->m_T.Count();
std::cout << "num_trim = " << num_trim << std::endl;
for (auto t_index=0;t_index<num_trim;t_index++)
{
const ON_BrepTrim& trim = brep->m_T[t_index];
std::cout << "m_type = " << trim.m_type << std::endl;
if (trim.Brep()) {
std::cout << "HAS BREP" << std::endl;
}else{
std::cout << "HAS NO BREP" << std::endl;
}
ON_NurbsCurve trim_nurbs_curve;
if (trim.NurbsCurve(&trim_nurbs_curve)) {
int num_cv = trim_nurbs_curve.CVCount();
std::cout << "Able to get trim as NURBS curve : num_cv = " << num_cv << std::endl;
for (auto tcv_index=0;tcv_index<num_cv;tcv_index++)
{
if (trim_nurbs_curve.IsRational())
{
ON_4dPoint cv;
trim_nurbs_curve.GetCV(tcv_index,cv);
std::cout << boost::format("Rational CV [%f,%f,%f,%f]") % cv.x % cv.y% cv.z% cv.w<< std::endl;
}
else
{
ON_3dPoint cv;
trim_nurbs_curve.GetCV(tcv_index,cv);
std::cout << boost::format("Non-rational CV [%f,%f,%f]") % cv.x % cv.y% cv.z << std::endl;
}
}
}
}
}
}
}
}
}
ON::End();
return 0;
}
All Breps have trim curves, whether or not the Brep has been “trimmed” or not. The diagram I referenced (above) shows this.
In the case of grid_2x2.3dm, ON_Brep::IsSurface() should return true because the Brep has a single face and that face is geometrically the same as the underlying surface.