31#include <wx/filename.h>
33#include <wx/stdpaths.h>
36#include <wx/wfstream.h>
37#include <wx/zipstrm.h>
40#include <decompress.hpp>
42#include <TDocStd_Document.hxx>
44#include <TopoDS_Shape.hxx>
45#include <Quantity_Color.hxx>
46#include <XCAFApp_Application.hxx>
48#include <AIS_Shape.hxx>
50#include <IGESControl_Reader.hxx>
51#include <IGESCAFControl_Reader.hxx>
52#include <Interface_Static.hxx>
54#include <STEPControl_Reader.hxx>
55#include <STEPCAFControl_Reader.hxx>
57#include <XCAFDoc_DocumentTool.hxx>
58#include <XCAFDoc_ColorTool.hxx>
59#include <XCAFDoc_ShapeTool.hxx>
61#include <BRep_Tool.hxx>
62#include <BRepMesh_IncrementalMesh.hxx>
65#include <TopoDS_Shape.hxx>
66#include <TopoDS_Face.hxx>
67#include <TopoDS_Compound.hxx>
68#include <TopExp_Explorer.hxx>
70#include <Quantity_Color.hxx>
71#include <Poly_Triangulation.hxx>
72#include <Poly_PolygonOnTriangulation.hxx>
73#include <Precision.hxx>
75#include <NCollection_Sequence.hxx>
76#include <TDF_Label.hxx>
77#include <TDF_ChildIterator.hxx>
78#include <TDF_Tool.hxx>
79#include <TDataStd_Name.hxx>
80#include <Standard_Version.hxx>
86#define MASK_OCE wxT( "PLUGIN_OCE" )
87#define MASK_OCE_EXTRA wxT( "PLUGIN_OCE_EXTRA" )
89typedef std::map<std::size_t, SGNODE*>
COLORMAP;
90typedef std::map<std::string, SGNODE*>
FACEMAP;
91typedef std::map<std::string, std::vector<SGNODE*>>
NODEMAP;
92typedef std::pair<std::string, std::vector<SGNODE*>>
NODEITEM;
97 std::vector< SGNODE* >* aItems );
101 std::vector< SGNODE* >* items, Quantity_ColorRGBA* color );
103#if OCC_VERSION_HEX >= 0x070500
104#define OCC_COLOR_SPACE Quantity_TOC_sRGB
106#define OCC_COLOR_SPACE Quantity_TOC_RGB
127 refColor.SetValues( Quantity_NOC_BLACK );
137 COLORMAP::iterator sC =
colors.begin();
138 COLORMAP::iterator eC =
colors.end();
157 FACEMAP::iterator sF =
faces.begin();
158 FACEMAP::iterator eF =
faces.end();
174 NODEMAP::iterator sS =
shapes.begin();
175 NODEMAP::iterator eS =
shapes.end();
179 std::vector< SGNODE* >::iterator sV = sS->second.begin();
180 std::vector< SGNODE* >::iterator eV = sS->second.end();
202 bool GetShape(
const std::string&
id, std::vector< SGNODE* >*& listPtr )
205 NODEMAP::iterator item;
208 if( item ==
shapes.end() )
211 listPtr = &item->second;
218 FACEMAP::iterator item;
219 item =
faces.find(
id );
221 if( item ==
faces.end() )
230 if(
nullptr == colorObj )
245 Quantity_Color colorRgb = colorObj->GetRGB();
250 std::size_t hash = std::hash<double>{}( colorRgb.Distance(
refColor ) )
251 ^ ( std::hash<float>{}( colorObj->Alpha() ) << 1 );
253 std::map<std::size_t, SGNODE*>::iterator item;
254 item =
colors.find( hash );
256 if( item !=
colors.end() )
283 wxFileName fname( wxString::FromUTF8Unchecked( aFileName ) );
284 wxFFileInputStream ifile( fname.GetFullPath() );
289 if( fname.GetExt().MakeUpper().EndsWith( wxT(
"STPZ" ) )
290 || fname.GetExt().MakeUpper().EndsWith( wxT(
"GZ" ) ) )
300 const int max_line_count = 3;
302 for(
int ii = 0; ii < max_line_count; ii++ )
304 memset( iline, 0, 82 );
305 ifile.Read( iline, 82 );
310 if( !strncmp( iline,
"ISO-10303-21;", 13 ) )
316 std::string fstr = iline;
320 if( fstr.find(
"urn:oid:1.0.10303." ) != std::string::npos )
326 if( iline[72] ==
'S' && ( iline[80] == 0 || iline[80] == 13 || iline[80] == 10 ) )
330 if( strncmp( iline,
"/*", 2 ) != 0 )
344void getTag(
const TDF_Label& aLabel, std::string& aTag )
346 std::ostringstream ostr;
348 if( aLabel.IsNull() )
350 wxLogTrace(
MASK_OCE, wxT(
"Null label passed to getTag" ) );
354 NCollection_List<int> tagList;
355 TDF_Tool::TagList( aLabel, tagList );
357 for(
const int& tag : tagList )
372 if( !aLabel.IsNull() && aLabel.FindAttribute( TDataStd_Name::GetID(),
name ) )
374 TCollection_ExtendedString extstr =
name->Get();
375 char* str =
new char[extstr.LengthOfCString() + 1];
376 extstr.ToUTF8CString( str );
378 txt = wxString::FromUTF8( str );
395 case TopAbs_COMPOUND:
return "COMPOUND";
396 case TopAbs_COMPSOLID:
return "COMPSOLID";
397 case TopAbs_SOLID:
return "SOLID";
398 case TopAbs_SHELL:
return "SHELL";
399 case TopAbs_FACE:
return "FACE";
400 case TopAbs_WIRE:
return "WIRE";
401 case TopAbs_EDGE:
return "EDGE";
402 case TopAbs_VERTEX:
return "VERTEX";
403 case TopAbs_SHAPE:
return "SHAPE";
415static inline std::ostream&
operator<<( std::ostream& aOStream,
const Quantity_ColorRGBA& aColor )
417 Quantity_Color rgb = aColor.GetRGB();
436 Handle( XCAFDoc_ColorTool ) aColorTool,
const char* aPreMsg =
nullptr )
438 if( aLabel.IsNull() )
444 TCollection_AsciiString entry;
445 TDF_Tool::Entry( aLabel, entry );
446 std::ostringstream ss;
447 ss << aPreMsg << entry <<
", " <<
getLabelName( aLabel )
448 << ( aShapeTool->IsShape( aLabel ) ?
", shape" :
"" )
449 << ( aShapeTool->IsTopLevel( aLabel ) ?
", topLevel" :
"" )
450 << ( aShapeTool->IsFree( aLabel ) ?
", free" :
"" )
451 << ( aShapeTool->IsAssembly( aLabel ) ?
", assembly" :
"" )
452 << ( aShapeTool->IsSimpleShape( aLabel ) ?
", simple" :
"" )
453 << ( aShapeTool->IsCompound( aLabel ) ?
", compound" :
"" )
454 << ( aShapeTool->IsReference( aLabel ) ?
", reference" :
"" )
455 << ( aShapeTool->IsComponent( aLabel ) ?
", component" :
"" )
456 << ( aShapeTool->IsSubShape( aLabel ) ?
", subshape" :
"" );
458 if( aShapeTool->IsSubShape( aLabel ) )
460 auto shape = aShapeTool->GetShape( aLabel );
461 if( !shape.IsNull() )
465 if( aShapeTool->IsShape( aLabel ) )
467 Quantity_ColorRGBA c;
468 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorGen, c ) )
470 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorSurf, c ) )
472 if( aColorTool->GetColor( aLabel, XCAFDoc_ColorCurv, c ) )
476 wxLogTrace(
MASK_OCE, ss.str().c_str() );
489 Handle( XCAFDoc_ColorTool ) aColorTool,
int aDepth = 0 )
491 std::string indent( aDepth * 2,
' ' );
492 printLabel( aLabel, aShapeTool, aColorTool, indent.c_str() );
493 TDF_ChildIterator it;
494 for( it.Initialize( aLabel ); it.More(); it.Next() )
495 dumpLabels( it.Value(), aShapeTool, aColorTool, aDepth + 1 );
503 if( data.m_color->
GetColor( label, XCAFDoc_ColorSurf, color ) )
505 else if( data.m_color->
GetColor( label, XCAFDoc_ColorCurv, color ) )
507 else if( data.m_color->
GetColor( label, XCAFDoc_ColorGen, color ) )
510 label = label.Father();
525 std::vector< SGNODE* >::iterator sL = lp->begin();
526 std::vector< SGNODE* >::iterator eL = lp->end();
545 IGESCAFControl_Reader reader;
546 IFSelect_ReturnStatus stat = reader.ReadFile( fname );
547 reader.PrintCheckLoad(
false, IFSelect_ItemsByEntity );
549 if( stat != IFSelect_RetDone )
553 if( !Interface_Static::SetIVal(
"read.precision.mode", 0 ) )
557 reader.SetColorMode(
true);
558 reader.SetNameMode(
false);
559 reader.SetLayerMode(
false);
561 if( !reader.Transfer( m_doc ) )
563 if( m_doc->CanClose() == CDM_CCS_OK )
570 if( reader.NbShapes() < 1 )
572 if( m_doc->CanClose() == CDM_CCS_OK )
584 wxLogTrace(
MASK_OCE, wxT(
"Reading step file %s" ), fname );
586 STEPCAFControl_Reader reader;
587 IFSelect_ReturnStatus stat = reader.ReadFile( fname );
589 if( stat != IFSelect_RetDone )
593 if( !Interface_Static::SetIVal(
"read.precision.mode", 1 ) )
597 if( !Interface_Static::SetRVal(
"read.precision.val",
ADVANCED_CFG::GetCfg().m_OcePluginLinearDeflection ) )
601 reader.SetColorMode(
true );
602 reader.SetNameMode(
false );
603 reader.SetLayerMode(
false );
605 if( !reader.Transfer( m_doc ) )
607 if( m_doc->CanClose() == CDM_CCS_OK )
614 if( reader.NbRootsForTransfer() < 1 )
616 if( m_doc->CanClose() == CDM_CCS_OK )
628 wxFileName fname( wxString::FromUTF8Unchecked( aFileName ) );
629 wxFFileInputStream ifile( fname.GetFullPath() );
631 wxFileName outFile( fname );
633 outFile.SetPath( wxStandardPaths::Get().GetTempDir() );
634 outFile.SetExt( wxT(
"STEP" ) );
636 wxFileOffset size = ifile.GetLength();
637 wxBusyCursor busycursor;
639 if( size == wxInvalidOffset )
643 bool success =
false;
644 wxFFileOutputStream ofile( outFile.GetFullPath() );
649 char *buffer =
new char[size];
651 ifile.Read( buffer, size);
652 std::string expanded;
656 expanded = gzip::decompress( buffer, size );
662 if( expanded.empty() )
666 wxZipInputStream izipfile( ifile );
667 std::unique_ptr<wxZipEntry> zip_file( izipfile.GetNextEntry() );
669 if( zip_file && !zip_file->IsDir() && izipfile.CanRead() )
671 izipfile.Read( ofile );
677 ofile.Write( expanded.data(), expanded.size() );
687 bool retval =
readSTEP( m_doc, outFile.GetFullPath().mb_str() );
690 wxRemoveFile( outFile.GetFullPath() );
700 Handle(XCAFApp_Application) m_app = XCAFApp_Application::GetApplication();
701 m_app->NewDocument(
"MDTV-XCAF", data.m_doc );
709 if( !
readIGES( data.m_doc, filename ) )
715 if( !
readSTEP( data.m_doc, filename ) )
728 if( m_app->CanClose( data.m_doc ) == CDM_CCS_OK )
729 m_app->Close( data.m_doc );
735 data.m_assy = XCAFDoc_DocumentTool::ShapeTool( data.m_doc->Main() );
736 data.m_color = XCAFDoc_DocumentTool::ColorTool( data.m_doc->Main() );
739 if( wxLog::IsAllowedTraceMask(
MASK_OCE ) )
741 dumpLabels( data.m_doc->Main(), data.m_assy, data.m_color );
745 NCollection_Sequence<TDF_Label> frshapes;
746 data.m_assy->GetFreeShapes( frshapes );
754 for(
int i = 1; i <= frshapes.Length(); i++ )
756 const TDF_Label& label = frshapes.Value( i );
758 if( data.m_color->IsVisible( label ) )
767 if( m_app->CanClose( data.m_doc ) == CDM_CCS_OK )
768 m_app->Close( data.m_doc );
776#if ( defined( DEBUG_OCE ) && DEBUG_OCE > 3 )
779 wxFileName fn( wxString::FromUTF8Unchecked( filename ) );
787 output.append( fn.GetName() );
788 output.append( wxT(
".wrl" ) );
794 data.
scene =
nullptr;
796 if( m_app->CanClose( data.m_doc ) == CDM_CCS_OK )
797 m_app->Close( data.m_doc );
804 std::vector<SGNODE*>* items, Quantity_ColorRGBA* color )
809 wxLogTrace(
MASK_OCE, wxT(
"Processing shell" ) );
810 for( it.Initialize( shape,
false,
false ); it.More(); it.Next() )
812 const TopoDS_Face& face = TopoDS::Face( it.Value() );
814 if(
processFace( face, data, parent, items, color ) )
823 std::vector< SGNODE* >* items )
827 Quantity_ColorRGBA col;
828 Quantity_ColorRGBA* lcolor =
nullptr;
830 data.
hasSolid = shape.ShapeType() == TopAbs_SOLID;
832 wxLogTrace(
MASK_OCE, wxT(
"Processing solid" ) );
835 if( !data.m_assy->Search( shape, label ) )
838 std::ostringstream ostr;
839 ostr <<
"KMISC_" << i++;
844 bool found_color =
false;
855 if( data.m_assy->Search( shape, label,
false,
true,
true ) &&
866 if( data.m_assy->Search( shape, label,
false,
false,
879 if( data.m_assy->Search( shape, label,
false,
false,
897 std::vector< SGNODE* >* component =
nullptr;
899 if( !partID.empty() )
906 if(
nullptr != items )
907 items->push_back( pptr );
911 std::vector<SGNODE*> itemList;
913 TopAbs_ShapeEnum stype = shape.ShapeType();
914 if( stype == TopAbs_SHELL )
916 if(
processShell( shape, data, pptr, &itemList, lcolor ) )
922 for( it.Initialize( shape,
false,
false ); it.More(); it.Next() )
924 const TopoDS_Shape& subShape = it.Value();
926 if( subShape.ShapeType() == TopAbs_SHELL )
928 if(
processShell( subShape, data, pptr, &itemList, lcolor ) )
933 wxLogTrace(
MASK_OCE, wxT(
"Unsupported subshape in solid" ) );
940 else if(
nullptr != items )
941 items->push_back( pptr );
948 std::vector<SGNODE*>* aItems )
950 std::string labelTag;
952 if( wxLog::IsAllowedTraceMask(
MASK_OCE ) )
955 getTag( aLabel, labelTag );
958 wxLogTrace(
MASK_OCE, wxT(
"Processing label %s" ), labelTag );
960 TopoDS_Shape originalShape;
961 TDF_Label shapeLabel = aLabel;
963 if( !aData.m_assy->
GetShape( shapeLabel, originalShape ) )
968 TopoDS_Shape shape = originalShape;
970 if( aData.m_assy->IsReference( aLabel ) )
972 wxLogTrace(
MASK_OCE, wxT(
"Label %s is ref, trying to pull up referred label" ),
975 if( !aData.m_assy->GetReferredShape( aLabel, shapeLabel ) )
980 labelTag =
static_cast<int>( shapeLabel.Tag() );
983 if( !aData.m_assy->
GetShape( shapeLabel, shape ) )
993 const TopLoc_Location& loc = originalShape.Location();
995 if( !loc.IsIdentity() )
997 wxLogTrace(
MASK_OCE, wxT(
"Label %d has location" ),
static_cast<int>( aLabel.Tag() ) );
998 gp_Trsf
T = loc.Transformation();
999 gp_XYZ coord =
T.TranslationPart();
1001 wxLogTrace(
MASK_OCE, wxT(
"Translation %f, %f, %f" ), coord.X(), coord.Y(), coord.Z() );
1005 if(
T.GetRotation( axis, angle ) )
1008 wxLogTrace(
MASK_OCE, wxT(
"Rotation %f, %f, %f, angle %f" ),
1009 axis.X(), axis.Y(), axis.Z(), angle );
1013 TopAbs_ShapeEnum stype = shape.ShapeType();
1019 case TopAbs_COMPOUND:
1023 if( !aData.m_assy->IsAssembly( shapeLabel ) )
1027 for( xp.Init( shape, TopAbs_SOLID ); xp.More(); xp.Next() )
1034 for( xp.Init( shape, TopAbs_SHELL, TopAbs_SOLID ); xp.More(); xp.Next() )
1041 for( xp.Init( shape, TopAbs_FACE, TopAbs_SHELL ); xp.More(); xp.Next() )
1043 const TopoDS_Face& face = TopoDS::Face( xp.Current() );
1044 processFace( face, aData, pptr, aItems,
nullptr );
1064 if(
processFace( TopoDS::Face( shape ), aData, pptr, aItems,
nullptr ) )
1073 if(
nullptr != aItems )
1074 aItems->push_back( pptr );
1076 if( !aData.m_assy->IsSimpleShape( shapeLabel ) && shapeLabel.HasChild() )
1078 wxLogTrace(
MASK_OCE, wxT(
"Label %s has children" ), labelTag );
1079 TDF_ChildIterator it;
1081 for( it.Initialize( shapeLabel ); it.More(); it.Next() )
1093 Quantity_ColorRGBA* color )
1095 if(
true == face.IsNull() )
1098 bool reverse = ( face.Orientation() == TopAbs_REVERSED );
1099 SGNODE* ashape =
nullptr;
1103 bool useBothSides =
false;
1108 useBothSides =
true;
1110 if( data.m_assy->FindShape( face, label,
false ) )
1113 if( !partID.empty() )
1114 ashape = data.
GetFace( partID );
1123 if(
nullptr != items )
1124 items->push_back( ashape );
1128 std::string id2 = partID;
1137 if(
nullptr != items )
1138 items->push_back( shapeB );
1144 TopLoc_Location loc;
1145 bool isTessellate (
false);
1146 Handle( Poly_Triangulation ) triangulation = BRep_Tool::Triangulation( face, loc );
1149 if( triangulation.IsNull() || triangulation->Deflection() > linDeflection + Precision::Confusion() )
1150 isTessellate =
true;
1154 BRepMesh_IncrementalMesh IM(face, linDeflection,
false,
1156 triangulation = BRep_Tool::Triangulation( face, loc );
1159 if( triangulation.IsNull() ==
true )
1162 Quantity_ColorRGBA lcolor;
1165 if( data.m_color->
GetColor( face, XCAFDoc_ColorSurf, lcolor )
1166 || data.m_color->
GetColor( face, XCAFDoc_ColorCurv, lcolor )
1167 || data.m_color->
GetColor( face, XCAFDoc_ColorGen, lcolor ) )
1186 std::vector< SGPOINT > vertices;
1187 std::vector< int > indices;
1188 std::vector< int > indices2;
1192 bool applyTransform = !loc.IsIdentity();
1193 gp_Trsf tx = applyTransform ? loc.Transformation() : gp_Trsf();
1195 for(
int i = 1; i <= triangulation->NbNodes(); i++ )
1197 gp_XYZ v = applyTransform ? triangulation->Node( i ).Transformed( tx ).Coord()
1198 : triangulation->Node( i ).Coord();
1199 vertices.emplace_back( v.X(), v.Y(), v.Z() );
1202 for(
int i = 1; i <= triangulation->NbTriangles(); i++ )
1205 triangulation->Triangle(i).Get(a, b, c);
1220 indices.push_back( a );
1221 indices.push_back( b );
1222 indices.push_back( c );
1226 indices2.push_back( b );
1227 indices2.push_back( a );
1228 indices2.push_back( c );
1233 coordIdx.
SetIndices( indices.size(), &indices[0] );
1237 if( !partID.empty() )
1244 std::string id2 = partID;
1253 coordIdx2.
SetIndices( indices2.size(), &indices2[0] );
1257 if( !partID.empty() )
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
bool SetDiffuse(float aRVal, float aGVal, float aBVal)
bool SetSpecular(float aRVal, float aGVal, float aBVal)
bool SetShininess(float aShininess) noexcept
bool SetAmbient(float aRVal, float aGVal, float aBVal)
bool SetTransparency(float aTransparency) noexcept
The wrapper for SGCOORDINDEX.
The wrapper for SGCOORDS.
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
The wrapper for the SGFACESET class.
bool CalcNormals(SGNODE **aPtr)
bool SetIndices(size_t nIndices, int *aIndexList)
Set the number of indices and creates a copy of the given index data.
bool SetParent(SGNODE *aParent)
Set the parent SGNODE of this object.
SGNODE * GetRawPtr(void) noexcept
Return the raw internal SGNODE pointer.
void Destroy(void)
Delete the object held by this wrapper.
The wrapper for the SGSHAPE class.
Define the basic data set required to represent a 3D model.
The base class of all Scene Graph nodes.
double m_OcePluginLinearDeflection
OCE (STEP/IGES) 3D Plugin Tesselation Linear Deflection.
collects header files for all SG* wrappers and the API
Handle(KICAD3D_INFO) KICAD3D_INFO
bool processShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
std::map< std::string, std::vector< SGNODE * > > NODEMAP
std::map< std::size_t, SGNODE * > COLORMAP
bool processFace(const TopoDS_Face &face, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items, Quantity_ColorRGBA *color)
std::pair< std::string, std::vector< SGNODE * > > NODEITEM
bool getColor(DATA &data, TDF_Label label, Quantity_ColorRGBA &color)
static int colorFloatToDecimal(float aVal)
void getTag(const TDF_Label &aLabel, std::string &aTag)
Gets the absolute tag string for a given label in the form of ##:##:##:##.
void addItems(SGNODE *parent, std::vector< SGNODE * > *lp)
std::string getShapeName(TopAbs_ShapeEnum aShape)
Gets a string for a given TopAbs_ShapeEnum element.
static void printLabel(TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, const char *aPreMsg=nullptr)
Gets a string for a given TopAbs_ShapeEnum element.
SCENEGRAPH * LoadModel(char const *filename)
static void dumpLabels(TDF_Label aLabel, Handle(XCAFDoc_ShapeTool) aShapeTool, Handle(XCAFDoc_ColorTool) aColorTool, int aDepth=0)
Dumps a label and the entire tree underneath it.
FormatType fileType(const char *aFileName)
bool readSTEP(Handle(TDocStd_Document)&m_doc, const char *fname)
static std::ostream & operator<<(std::ostream &aOStream, const Quantity_ColorRGBA &aColor)
bool processSolidOrShell(const TopoDS_Shape &shape, DATA &data, SGNODE *parent, std::vector< SGNODE * > *items)
static wxString getLabelName(const TDF_Label &aLabel)
bool processLabel(const TDF_Label &aLabel, DATA &aData, SGNODE *aParent, std::vector< SGNODE * > *aItems)
std::map< std::string, SGNODE * > FACEMAP
bool readSTEPZ(Handle(TDocStd_Document)&m_doc, const char *aFileName)
bool readIGES(Handle(TDocStd_Document) &m_doc, const char *fname)
SGLIB_API bool WriteVRML(const char *filename, bool overwrite, SGNODE *aTopNode, bool reuse, bool renameNodes)
Write out the given node and its subnodes to a VRML2 file.
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Delete the given SG* class node.
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
static SGNODE * getColor(IFSG_SHAPE &shape, int colorIdx)
Handle(XCAFDoc_ColorTool) m_color
SGNODE * GetFace(const std::string &id)
Handle(TDocStd_Document) m_doc
bool GetShape(const std::string &id, std::vector< SGNODE * > *&listPtr)
Handle(XCAFDoc_ShapeTool) m_assy
SGNODE * GetColor(Quantity_ColorRGBA *colorObj)