Visualize OCC shape in Open Inventor

Hello,
I’ve tried to visualize a TopoDS_Shape in Open Inventor, transforming every face of my shape in a nurbs surface. I used the following code to do that, and it works if my shape is a prism, while if my shape is a sphere or a cone, it doesn’t work. I get a strange surface.
What’s wrong? Please help me.

I get this code from “OpenCASCADE BRep viewer” project (http://projects.opencascade.org/projects/graphperf/coin3d.htm).

In this code there's also an algorithm to mesh every surface of the shape, but I need to transform the shape in a set of nurbs surface. So I can check if the surface is flat, checkig if the control points are complanar...

This is the shape2nurbs code:

void occShape2OIVNurbs(TopoDS_Shape myShape, SoSeparator *solidSep) {

//-----------------------
// Use OpenGL NURBS
//-----------------------

TopExp_Explorer ex;
for (ex.Init(myShape, TopAbs_FACE); ex.More(); ex.Next()) {

float* mySurfaceVKnots;
float* mySurfaceUKnots;
int myNbVKnots;
int myNbUKnots;

const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
Handle(Geom_Surface) aGeomSurface = BRep_Tool::Surface(aFace);
Handle(Geom_BSplineSurface) aBSplineSurface;
Standard_Boolean ok = false;
if(aGeomSurface->DynamicType() != STANDARD_TYPE(Geom_BSplineSurface)) {
// try to convert into nurbs
BRepBuilderAPI_NurbsConvert nbscv;
nbscv.Perform(aFace);
if (nbscv.IsDone()){
aGeomSurface = BRep_Tool::Surface(TopoDS::Face(nbscv.Shape()));
ok = true;
}
}
else ok = true;

if(ok) {
aBSplineSurface = Handle(Geom_BSplineSurface)::DownCast(aGeomSurface);

int myNbUPoles = aBSplineSurface->NbUPoles();
int myNbVPoles = aBSplineSurface->NbVPoles();

TColgp_Array2OfPnt aPoles(1, myNbVPoles, 1, myNbUPoles);

TColStd_Array1OfReal aVKnots(1, aBSplineSurface->NbVKnots());
TColStd_Array1OfReal aUKnots(1, aBSplineSurface->NbUKnots());

aBSplineSurface->Poles(aPoles);
aBSplineSurface->UKnots(aUKnots);
aBSplineSurface->VKnots(aVKnots);

//Push the nurbs in Coin3d

// Control Point
Standard_Integer i, j, aCounter;
int aLength = myNbVPoles*myNbUPoles; //Create array of control points and their weights

SbVec4f* mySurfaceCtrlPoints = new SbVec4f[aLength];
if(mySurfaceCtrlPoints == NULL) return;

aCounter = -1;

for(j = 1; j for(i = 1; i const gp_Pnt& aPoint = aBSplineSurface->Pole(i, j); //Control point (U,V)
mySurfaceCtrlPoints[++aCounter].setValue((float)(aPoint.X()),(float)(aPoint.Y()),(float)(aPoint.Z()),(float)(aBSplineSurface->Weight(i, j)));
}
}

TColStd_ListOfReal aListOfKnot;
TColStd_ListIteratorOfListOfReal aListOfKnotIterator;

try {
//Fill the knot`s array taking into account multiplicities
// VKnots
for(i = aVKnots.Lower(); i for(j = 1; jVMultiplicity(i); j++)
aListOfKnot.Append(aVKnots(i));
}

mySurfaceVKnots = new float[aListOfKnot.Extent()];
if(mySurfaceVKnots == NULL) return;

aCounter = -1;
for(aListOfKnotIterator.Initialize(aListOfKnot); aListOfKnotIterator.More(); aListOfKnotIterator.Next()) {
mySurfaceVKnots[++aCounter] = (float)(aListOfKnotIterator.Value());
}
myNbVKnots = aCounter+1;

// UKnots
aListOfKnot.Clear();
for(i = aUKnots.Lower(); i for(j = 1; jUMultiplicity(i); j++)
aListOfKnot.Append(aUKnots(i));
}

mySurfaceUKnots = new float[aListOfKnot.Extent()];
if(mySurfaceUKnots == NULL) return;

aCounter = -1;
for(aListOfKnotIterator.Initialize(aListOfKnot); aListOfKnotIterator.More(); aListOfKnotIterator.Next()) {
mySurfaceUKnots[++aCounter] = (float)(aListOfKnotIterator.Value());
}
myNbUKnots = aCounter+1;
}
catch(Standard_Failure) {
continue;
}

//Nurbs definition
SoNurbsSurface* surface = new SoNurbsSurface;
SoCoordinate4 *controlPts = new SoCoordinate4;
SoComplexity *comp = new SoComplexity;
comp->type.setValue(SoComplexity::OBJECT_SPACE);
comp->value = 0.5;
controlPts->point.setValues(0,aLength,mySurfaceCtrlPoints);
surface->numUControlPoints.setValue(myNbUPoles);
surface->numVControlPoints.setValue(myNbVPoles);
surface->uKnotVector.setValues(0, myNbUKnots, mySurfaceUKnots);
surface->vKnotVector.setValues(0, myNbVKnots, mySurfaceVKnots);
solidSep->addChild(comp);
solidSep->addChild(controlPts);
solidSep->addChild(surface);

delete [] mySurfaceVKnots;
delete [] mySurfaceUKnots;

}
}
}

Anup's picture

Hi Patrik,

I ve tried searching for IvTools like u told but i didn't found in coin3D folder i searched in net it s another tool of coin3d i couldn't get how to install that library, So i was searching another method to do tat,
Patrik can u tell me whether i can use getBoundingBox() method or SoTransformSeparator to get the translated value frm sceneGraph and export it into a file??

Thanks & Regards

Patrik Mueller's picture

Hi Anup,

if I remember correctly exporting your root node from the OpenInventor SceneGraph with STL should transform the STL output by itself (means: transforming all IndexedFaceSets to absolute values).

Greets,

Patrik

Anup's picture

Hi Patrik,

I want to do boolean operation on two objects beased on Co-ordinates picked by users using SoPicketpoint in Coin3D, Meaning user can 3 points a1,a2,a3 from Object A and 3 points b1,b2,b3 from object B, then have to do boolean operation to these a1+b1,a2+b2,a3+b3. can i do this function in coin3D or i have to do this in OpenCascade??

Greets,
Anup

Patrik Mueller's picture

Hi Anup,

I don't know if such functionality exists in OCC. Perhaps GTS (http://gts.sourceforge.net/) could give you some hints how to do CSG with meshes if you have to use meshes...

Greets,

Patrik

Anup's picture

Hi Patrik,

Oh there are features in GTS Library which can help me, The pipeline of my applicztion is like this.

IGES/STL -> OCC Library -> Coin3D(IndexedFaceset)

Will the GTS Library supports OpenInventor Data Structure?? i mean i need to perform GTS Library functions on SoNode.

Greets,
Anup S

Patrik Mueller's picture

Hi Anup,

GTS was an example for CSG with meshes - but converting mesh structures like SoIndexedFaceSet or OCC PolyTriangulation shouldn't be a problem. Don't know about your application - but remember GTS is GPL! VTK also has CSG methods for meshes. If you search on the web, you will find more solutions...

Greets,

Patrik

Anup's picture

Hi Patrik,

I l do the boolean operation later right now i need to do Translation on STL File Imported to Coin3D, I want to tanslate the SoNode to the User-Specified Co-Ordinate System. Is it Possible in OpenInventor or OpenCascade?? The Visualization in my environment is STL -> OCC -> Coin3D Viewer.

Greets,
Anup S

Anup's picture

Hi Patrik,

I l do the boolean operation later right now i need to do Translation on STL File Imported to Coin3D, I want to tanslate the SoNode to the User-Specified Co-Ordinate System. Is it Possible in OpenInventor or OpenCascade?? The Visualization in my environment is STL -> OCC -> Coin3D Viewer.

Greets,
Anup S

Patrik Mueller's picture

Hi Anup,

take a look at SoTransform...

Greets,

Patrik

Anup's picture

Hi Patrik,

I looked into SoTransform, The translation is working on SoCube or SoCone but its not working on SoNode i.e., The Following will show u the body of the code.

SoSeparator *STLRoot = new SoSeparator;
// Read IGES File
// Construct SoIndexedFaceset

SoTransform *STLXform = new SoTransform;
STLXform->translation.setValue(-4.5548072,5.8638220,-36.812164);
STLRoot_01->addChild(STLXform);

The Translation Value which i am hard-coding is another SoSeparator or IGES File.
The Shape is not Tanslated.

Greets,
Anup

Anup's picture

Hi Patrik,

It s Read STL File in earlier post Sorry not IGES.

SoSeparator *STLRoot = new SoSeparator;
// Read STL File
// Construct SoIndexedFaceset

SoTransform *STLXform = new SoTransform;
STLXform->translation.setValue(-4.5548072,5.8638220,-36.812164);
STLRoot_01->addChild(STLXform);

The Translation Value which i am hard-coding is another SoSeparator or STL File.
The Shape is not Tanslated.

Greets,
Anup

Anup's picture

Hi Patrik,

I was able to apply Translation.setvalue() using SoTransform for SoCube,SoCone,SoSphere but i could not apply the same thing for SoSeparator which contains the data using IndexedFaceSet Method. Please tell me how can i do translation for SoSeaparator. This really pushes my app to new level.

Thanks & Regards
Anup

Patrik Mueller's picture

Hi Anup,

cool about you progress! You can't apply a matrix to a SoSeparator, but you can use a SoTransform as a parent of your SoSeparator.

Greets,

Patrik

Anup's picture

Hi Patrik,

I tried adding SoTransform to parent it didin't worked, So i am trying to do the translation in OpenCascade Module itself, So i found out gp_Trsf can be Used for Translation, Rotation and Scaling for TopoDs_Shape. CAn u tell me which function can i use to perform translation of TopoDS_Shape to Specified Co-Ordinates??

void SetDisplacement(const gp_Ax3& FromSystem1,const gp_Ax3& ToSystem2) ;
void SetTransformation(const gp_Ax3& FromSystem1,const gp_Ax3& ToSystem2) ;
void SetTransformation(const gp_Ax3& ToSystem) ;
void SetTransformation(const gp_Quaternion& R,const gp_Vec& T) ;
void SetTranslation(const gp_Vec& V) ;
void SetTranslation(const gp_Pnt& P1,const gp_Pnt& P2) ;
void SetTranslationPart(const gp_Vec& V) ;

Anup's picture

Hi Patrik,

Actually i need to clear the contents on the SceneGraph in Examiner Viewer or refresh it to display new root node in it i.e., How to clear the SceneGraph in Examiner Viewer and set a new Root Node??... how can i do this??

Greets,
Anup

Patrik Mueller's picture

Hi Anup,

please start to study some OIV tutorials!!!

Best regards,

Patrik

Anup's picture

Hi Patrik,

I am so sorry for asking this again but i am getting cnfused, Actually i went through some blogs and The Iventor Mentor.pdf they are saying if i do like this SelectionRoot->unref(); will reduce the reference count and the root will be unreferenced, But i am still having that root in the viewer when i set another root to the viewer the selection root is still there in the Viewer canvas.

Thanks & Regards
Anup

Patrik Mueller's picture

Hi Anup,

unref is like a smart ptr. Are you sure all references are relased? As a second check create an empty node and assign it to the viewer.

Greets,

Patrik

Anup's picture

Hi Patrik,

Do you know how to display that small co-ordinate axis(x,y,z) on bottom on coin3d Viewer?? It will rotate when the objects in scenegraph rotates. I am not getting whether i should do that in OpenGL or there is a class for that in coin3D, I am searching for it but couldn't find anything related to that.

Greets,
Anup

Anup's picture

Hi Patrik,

                 Right now i am facing a weird issue. I havent faced this earlier, I have written a code to convert from IGES/IGS file to STL file. When i was using OCC-6.6.0 this code was working perfectly, Due to some reasons i had to migrate to Visual studio 2013 so i downloaded OCC 6.9.1, Now i am facing with weird issue which i am not able to resolve. I have attached screenshot while i debug you can have a look at it. The following is my code

    IGESControl_Controller::Init();
    IGESControl_Reader My_reader;

    Standard_Integer status = My_reader.ReadFile(file);

    status = My_reader.TransferRoots();

    /// The shape stores all translated data as single shape
    IGES_Shape = My_reader.OneShape();

    status = IGES_Shape.IsNull(); //  <--- --- ---- over here the status value is 0 i.e., Standard_boolean value is false /// so the shape is not NULL
    

    StlAPI_Writer wr;
    status = wr.Write(IGES_Shape, "temp/IGES_Temp.stl"); // <- - --- --------- ( over here the status value is 1 i.e., //StlAPI_ErrorStatus = StlAPI_MeshIsEmpty  which is showing me that the mesh is empty.)

Please help me out. I havent faced with this issue earlier.

Anup's picture

Hi Patrik,

I have tried with an example to read iges visualize .iges file using SoIndexedFacet, I hav attached a file with the code can you please tell me if anything is wrong in that??

The file is not getting displayed

Thanks & Regards
Anup S

Patrik Mueller's picture

Hi Anup,

meshing inside STL writing was removed in 6.9.0:

"STL writer does not check the given shape for existing triangulation and meshes it again using BrepMesh in force mode.
Meshing functions have been completely removed from StlTransfer. Now StlWriter can return error status, for example, if a mesh of the passed shape is empty."

So you have to mesh IGES_Shape before writing.

Greets,

Patrik

Anup's picture

Hi Patrik,

              To mesh IGES_Shape i use the below code. But it seems like they have taken out the meshing out of BrepMesh function.

                            BRepMesh::Mesh(IGES_Shape, 0.01); // <----- ------------ The Mesh() function does not exists in BrepMesh

               Now Which function i can use to mesh the TopoDS_Shape IGES_Shape?? Please let me know.

Thanks,

Anup S

Patrik Mueller's picture

Hi Anup,

check the triangulation sample from OCC.

Greets,

Patrik

Anup's picture

Hi Patrik,

               I checked in samples of triangluation exaple. The previous version of meshing they have greyed it out. So i used with the following code. They have used 'BRepMesh_IncrementalMesh'. Now it is working.

BRepTools::Clean(IGES_Shape);
BRepMesh_IncrementalMesh(IGES_Shape, 0.01);

StlAPI_Writer wr;
status = wr.Write(IGES_Shape, "temp/IGES_Temp.stl");

               Now the write function is taking a lot of time to write the file nad when i render the stl File it will render very slowly. Am i doing this correct??

Thanks,

Anup

Patrik Mueller's picture

Hi Anup,

writing and rendering depends on the deflection parameter. The more triangles you get the more triangles have to be written and rendered.

Greets,

Patrik

Anup's picture

Hi Patrik,

              Thank you for the answer. I have one more Question, Now what i have is an STL File i want to create patches on top of this STL file and create nurbs surfaces on these patches so it will be like creating NURBS surface from Mesh file. I have sent one link at the bottom you just watch the video and let me know how i can achieve this task. Whether OpenCascade has this support or any library other libraries which i can use. Please help me out in this difficult task.

Video Link : https://www.youtube.com/watch?v=E83iNsbpsPk 

Thanks,

Anup S

Anup's picture

Hi Patrik,

              Or shall i build previous version of OCC instead of using OCC 6.9 which is giving me lot of headache. Which previous version of OCC can be built in VC2012 ??

Thanks,

Anup S