Trim Curve CV requires transformation?

I am trying to write my own *.3dm translator and in the process of studying the generated *.rib and the opennurbs_gl.cpp code.

When I print out the CV of a trim curve, I see data like these

NOTE : my own print out formatting
Order : 3
Min/Max : {0,30.0174}
Knots : [ 0 0 0 7.50435 7.50435 15.0087 15.0087 22.5131 22.5131 30.0174 30.0174 30.0174 ]
CVs : (13.4977 9.43825 0)
(12.4828 14.1066 0)
(7.81446 13.0918 0)
(3.14608 12.0769 0)
(4.16095 7.40852 0)
(5.17581 2.74014 0)
(9.84419 3.755 0)
(14.5126 4.76987 0)
(13.4977 9.43825 0)

but when I look at the generated data for RiTrimCurve in the *.rib generated from Rhino, I see the following

TrimCurve [ 1 ] [ 3 ] [ 0 0 0 7.50435 7.50435 15.0087 15.0087 22.5131 22.5131 30.0174 30.0174 30.0174 ] [ 0 ] [ 30.0174 ] [ 9 ] [ 0.768786 0.502741 0.445087 0.126707 0.236994 0.208453 0.560694 0.584487 0.768786 ] [ 0.556886 0.58855 0.772455 0.503867 0.437126 0.114323 0.221557 0.199006 0.556886 ] [ 1 0.707107 1 0.707107 1 0.707107 1 0.707107 1 ]

I am familiar with the RenderMan API, I am interested in what sort of transformation was constructed and applied to the CV data from the OpenNURBS library before they are submitted to the RiTrimCurve call, this will help me understand what is going on.

In the above example, using the first value as a comparison

CV[0].x is 13.4977 from the OpenNURBS library retrieval call

CV[0].x is 0.768786 is supplied to the RtFloat u[] parameter in the call to RiTrimCurve

Hope someone is able to shed some light.

Cheers

Can you post your sample geometry?

QuadCircleTrim.3dm (43.8 KB)

Here is the sample geometry

The file has some issues. What version of Rhino did you use to create this model?

Using the example file v5_my_trimmed_surface.3dm OpenNURBS’s examples, from dumping out the trim curve CV, I see values like (there are 3 curves use for trimming)

CVs : (1 2 0)
(9 1.5 0)
CVs : (9 1.5 0)
(7 8 0)
CVs : (7 8 0)
(1 2 0)

Whereas the RIB representation is in parametric space [0.0 1.0]

TrimCurve [ 3 ] [ 2 2 2 ] [ 0 0 0.801561 0.801561 0 0 0.680074 0.680074 0 0 0.848528 0.848528 ] [ 0 0 0 ] [ 0.801561 0.680074 0.848528 ] [ 2 2 2 ] [ 0.1 0.9 0.9 0.7 0.7 0.1 ] [ 0.2 0.15 0.15 0.8 0.8 0.2 ] [ 1 1 1 1 1 1 ]

Are the parameteric representation of the trim curves available/retrievable via OpenNURBS or do I need to perform the projection myself ?

If it is a few API calls to OpenNURBS, I will continue, otherwise, I plan to stop as it will be too involved to write all the matrix projection code.

Cheers

Looking at all this in a debug version of Rhino, the RIB output is correct.

Are you sure your own print output code is correct? Trim curves are 2D curves and are stored in the ON_Brep::m_C2 array.

Perhaps your own print output code is printing the CVs from a curve in the ON_Brep::m_C3 array?

Yes, I am attempting to get the information from m_C2, maybe the way I retrieve the m_C2 is incorrect and as such, don’t get the parametric value and some other values instead, here is the code as it currently is

`
std::cout << “process_brep_face 00100” << std::endl;
const ON_Brep* brep = face.Brep();
if ( !brep )
return;

int m_C2_Count = brep->m_C2.Count();
{
    for (int tcIndex = 0; tcIndex < brep->m_C2.Count(); tcIndex++)
    {
        const ON_Curve* tc = brep->m_C2[tcIndex];
        bool tc_is_closed = tc->IsClosed();
        int tc_has_nurb_form = tc->HasNurbForm();
        std::cout << boost::format("tc_is_closed = %1%, tc_has_nurb_form = %2%")
            % (tc_is_closed?"true":"false") % tc_has_nurb_form << std::endl;
        ON_NurbsCurve nurbs_tc;
        if (tc->GetNurbForm(nurbs_tc)>0)
        {
            std::cout << "process_brep_face 00500" << std::endl;
            int ntc_dim = nurbs_tc.m_dim;
            int ntc_cv_count = nurbs_tc.m_cv_count;
            std::cout << boost::format("ntc_dim = %1%, ntc_cv_count = %2%")
                % ntc_dim % ntc_cv_count << std::endl;
            std::cout << boost::format("m_cv[0] = %1%") % nurbs_tc.m_cv[0] << std::endl;
        }
    }
}
printf("m_C2_Count = %d\n",m_C2_Count);

`

If I’m not mistaken it is possible for a 2d trim curve to be reversed in parameter space w.r.t. the 3d curve it represents. I think, for example, on an untrimmed surface, that the boundary curves are in the same direction (clockwise or anti-clockwise), whereas the north- and south 2d trim curves are “parallel” and the east and west 2d trim curves too.

The public boolean member variable for this can be found on the corresponding ON_Trim object, and is called m_bRev3d.

Take a look and see if that can explain what you are seeing.

Before writing a Brep, the RIB exporter changes the parameterization of each face:

ON_Interval udom, vdom;
udom.Set(0.0, 1.0);
vdom.Set(0.0, 1.0);
for (int fi = 0; fi < pBrep->m_F.Count(); fi++)
{
  ON_BrepFace* pF = pBrep->Face(fi);
  if (pF)
  {
    // This changes the parameterization of the face's surface and transforms
    // the "u" and "v" coordinates of all the face's parameter space trimming
    // curves. The locus of the face is not changed.
    pF->SetDomain(udom, vdom);
  }
}

Hope this helps.

– Dale

Hi Dale,

Yes, it’s the Domain which I need to set to get a matching value for the Trim Curve.

Thank you for the insight. My translator should work properly now.

Cheers