PatriciaTrieNode<S,T>* PatriciaTrie<S,T>::find_bitindex_node (PatriciaTrieNode<S,T>* root, int bitindex) {
  
  //
  // is the head-pseudo-node requested?
  //

  if (bitindex == -1)
    return head;

  //
  // check all the normal nodes
  //

  NODE_LIST nodes = GetNodeList (root);
  
  NODE_LIST_ITERATOR i  = nodes.begin ();
  NODE_LIST_ITERATOR iend = nodes.end   ();

  for ( ; i != iend; i++) {
    PatriciaTrieNode<S,T>* node = *i;
    if (node->bit_index == bitindex) return node;
  }

  return NULL;
}
bool X3D_MODEL_PARSER::Load( const wxString& aFilename )
{
    wxLogTrace( traceX3DParser, wxT( "Loading: %s" ), GetChars( aFilename ) );

    wxXmlDocument doc;

    if( !doc.Load( aFilename ) )
    {
        wxLogTrace( traceX3DParser, wxT( "Error while parsing file: %s" ), GetChars( aFilename ) );
        return false;
    }

    if( doc.GetRoot()->GetName() != wxT( "X3D" ) )
    {
        wxLogTrace( traceX3DParser, wxT( "Filetype is not X3D: %s" ), GetChars( aFilename ) );
        return false;
    }

    // Switch the locale to standard C (needed to print floating point numbers)
    LOCALE_IO toggle;

    childs.clear();

    // Shapes are inside of Transform nodes
    // Transform node contains information about
    // transition, scale and rotation of the shape
    NODE_LIST transforms;
    GetChildsByName( doc.GetRoot(), wxT( "Transform" ), transforms );

    for( NODE_LIST::iterator node_it = transforms.begin();
         node_it != transforms.end();
         node_it++ )
    {
        m_model.reset( new S3D_MESH() );
        childs.push_back( m_model );

        wxXmlNode* node = *node_it;
        wxXmlAttribute* prop = node->GetAttributes();

        wxLogTrace( traceX3DParser, wxT( "Transform: %s %s" ), prop->GetName(), prop->GetValue() );

        readTransform( node );


    }

    return true;
}
void X3D_MODEL_PARSER::readTransform( wxXmlNode* aTransformNode )
{
    NODE_LIST childnodes;

    GetChildsByName( aTransformNode, wxT( "Material" ), childnodes );

    for( NODE_LIST::iterator node = childnodes.begin();
         node != childnodes.end();
         node++ )
    {
        readMaterial( *node );
    }

    childnodes.clear();

    PROPERTY_MAP properties;

    GetNodeProperties( aTransformNode, properties );



    GetChildsByName( aTransformNode, wxT( "IndexedFaceSet" ), childnodes );

    for( NODE_LIST::iterator node = childnodes.begin();
         node != childnodes.end();
         node++ )
    {
        readIndexedFaceSet( *node, properties );
    }

    childnodes.clear();
}
typename PatriciaTrie<S,T>::NODE_LIST PatriciaTrie<S,T>::GetNodeList (PatriciaTrieNode<S,T>* root) {

  NODE_LIST       retNodes;
  NODE_LIST       newItemsLeft, newItemsRight;
  PatriciaTrieNode<S,T>*  startNode = (root == NULL ? head : root);

  //
  // insert the current node if it is not the root node
  //

  if (startNode->bit_index >= 0)
    retNodes.insert (retNodes.end (), startNode);

  //
  // walk down left wing
  //

  if (startNode->left != NULL && startNode->left->bit_index > startNode->bit_index) 
    newItemsLeft = GetNodeList (startNode->left);
  
  retNodes.insert (retNodes.end(), newItemsLeft.begin(), newItemsLeft.end());

  //
  // walk down right wing
  //

  if (startNode->right != NULL && startNode->right->bit_index > startNode->bit_index)
    newItemsRight = GetNodeList (startNode->right);

  retNodes.insert (retNodes.end(), newItemsRight.begin(), newItemsRight.end());

  return retNodes;
}
/* Steps:
 * 1. Read transform data
 * 2. Read vertex triplets
 * 3. Read coordinate indexes
 * 4. Apply geometry to Master object
 */
void X3D_MODEL_PARSER::readIndexedFaceSet( wxXmlNode* aFaceNode,
        PROPERTY_MAP& aTransformProps )
{
    /* Step 1: Read transform data
     * --------------------------- */

    S3D_VERTEX translation;

    parseDoubleTriplet( aTransformProps[ wxT( "translation" ) ], translation );

    S3D_VERTEX scale;
    parseDoubleTriplet( aTransformProps[ wxT( "scale" ) ], scale );

    S3D_VERTEX rotation;
    double angle = 0.0;
    wxStringTokenizer tokens( aTransformProps[ wxT( "rotation" ) ] );

    double x = 0.0, y = 0.0, z = 0.0;

    if( !( tokens.GetNextToken().ToDouble( &x )
           && tokens.GetNextToken().ToDouble( &y )
           && tokens.GetNextToken().ToDouble( &z )
           && tokens.GetNextToken().ToDouble( &angle ) ) )
    {
        // DBG( printf( "rotation read error" ) );
    }
    else
    {
        rotation.x  = x;
        rotation.y  = y;
        rotation.z  = z;
    }

    /* Step 2: Read all coordinate points
     * ---------------------------- */
    std::vector<double> points;
    NODE_LIST coordinates;
    GetChildsByName( aFaceNode, wxT( "Coordinate" ), coordinates );

    PROPERTY_MAP coordinate_properties;
    // IndexedFaceSet has one Coordinate child node
    GetNodeProperties( coordinates[0], coordinate_properties );

    // Save points to vector as doubles
    wxStringTokenizer point_tokens( coordinate_properties[ wxT( "point" ) ] );
    double point = 0.0;

    while( point_tokens.HasMoreTokens() )
    {
        if( point_tokens.GetNextToken().ToDouble( &point ) )
        {
            points.push_back( point );
        }
        else
        {
            wxLogTrace( traceX3DParser, wxT( "Error converting to double" ) );
        }
    }

    if( points.size() % 3 != 0 )
    {
        // DBG( printf( "Number of points is incorrect" ) );
        return;
    }

    /* Create 3D vertex from 3 points and
     * apply transforms in order of SCALE, ROTATION, TRANSLATION
     */
    wxString vrml_pointlist;
    std::vector<S3D_VERTEX> triplets;

    for( unsigned id = 0; id < points.size() / 3; id++ )
    {
        int triplet_indx = id * 3;
        S3D_VERTEX point( points[ triplet_indx ],
                points[ triplet_indx + 1 ],
                points[ triplet_indx + 2 ] );

        point.x *= scale.x;
        point.y *= scale.y;
        point.z *= scale.z;

        rotate( point, rotation, angle );

        point.x += translation.x;
        point.y += translation.y;
        point.z += translation.z;

        m_model->m_Point.push_back( point );

        // VRML
        vrml_pointlist.Append( wxString::Format( wxT( "%f %f %f\n" ), point.x, point.y, point.z ) );
    }

    vrml_points.push_back( vrml_pointlist );


    /* Step 3: Read all color points
     * ---------------------------- */
    std::vector<double> color_points;
    NODE_LIST color;
    GetChildsByName( aFaceNode, wxT( "Color" ), color );

    // Some models lack color information, need to handle this safely
    if( !color.empty() )
    {
        PROPERTY_MAP color_properties;
        // IndexedFaceSet has one Coordinate child node
        GetNodeProperties( color[0], color_properties );

        // Save points to vector as doubles
        wxStringTokenizer colorpoint_tokens( color_properties[ wxT( "color" ) ] );
        double color_point = 0.0;

        while( colorpoint_tokens.HasMoreTokens() )
        {
            if( colorpoint_tokens.GetNextToken().ToDouble( &color_point ) )
            {
                color_points.push_back( color_point );
            }
            else
            {
                wxLogTrace( traceX3DParser, wxT( "Error converting to double" ) );
            }
        }

        if( color_points.size() % 3 != 0 )
        {
            // DBG( printf( "Number of points is incorrect" ) );
            return;
        }

        /* Create 3D face color from 3 color points
         */
        m_model->m_Materials->m_DiffuseColor.clear();

        for( unsigned id = 0; id < color_points.size() / 3; id++ )
        {
            m_model->m_MaterialIndexPerFace.push_back( id );

            int color_triplet_indx = id * 3;
            glm::vec3 colorface( color_points[ color_triplet_indx + 0 ],
                    color_points[ color_triplet_indx + 1 ],
                    color_points[ color_triplet_indx + 2 ] );

            m_model->m_Materials->m_DiffuseColor.push_back( colorface );
        }
    }


    /* -- Read coordinate indexes -- */
    PROPERTY_MAP faceset_properties;
    GetNodeProperties( aFaceNode, faceset_properties );

    wxString coordIndex_str = faceset_properties[ wxT( "coordIndex" ) ];
    wxStringTokenizer index_tokens( coordIndex_str );

    wxString vrml_coord_indx_list;

    std::vector<int> coord_list;
    coord_list.clear();

    while( index_tokens.HasMoreTokens() )
    {
        long index = 0;

        index_tokens.GetNextToken().ToLong( &index );

        // -1 marks the end of polygon
        if( index < 0 )
        {
            /* Step 4: Apply geometry to Master object
             * --------------------------------------- */
            m_model->m_CoordIndex.push_back( coord_list );

            coord_list.clear();
            vrml_coord_indx_list.Append( wxT( "-1\n" ) );
        }
        else
        {
            coord_list.push_back( index );
            vrml_coord_indx_list.Append( wxString::Format( wxT( "%ld " ), index ) );
        }
    }

    vrml_coord_indexes.push_back( vrml_coord_indx_list );
}
PatriciaTrie<S,T>* PatriciaTrie<S,T>::Copy (PatriciaTrieNode<S,T>* root) {

  PatriciaTrieNode<S,T>* newNode = new PatriciaTrieNode<S,T> ();
  bool recursiveHead = (root == NULL);
  if (root == NULL) root = head;

  newNode->bit_index  = root->bit_index;
  newNode->data   = root->data;
  newNode->key    = root->key;

  //
  // create the subtrees and wire my children to it
  // or (if there are no subtrees) wire the children to myself
  // later we will wire the children correctly with some backedges
  //

  if (root->left != NULL && root->left->bit_index > root->bit_index) {
    PatriciaTrie<S,T>* leftTrie = Copy (root->left);
    newNode->left = leftTrie->head;
    leftTrie->head = NULL;
    delete leftTrie;
  } else {
    newNode->left = newNode;
  }

  if (root->right != NULL && root->right->bit_index > root->bit_index) {
    PatriciaTrie<S,T>* rightTrie = Copy (root->right);
    newNode->right = rightTrie->head;
    rightTrie->head = NULL;
    delete rightTrie;
  } else {
    newNode->right = newNode;
  }

  PatriciaTrie<S,T>* newTrie = new PatriciaTrie<S,T> ();
  newTrie->head = newNode;

  //
  // need to adapt the back edges
  //

  if (recursiveHead) {

    NODE_LIST origNodes = GetNodeList ();
    NODE_LIST newNodes  = newTrie->GetNodeList ();

    assert (origNodes.size() == newNodes.size());

    NODE_LIST_ITERATOR iorigBegin = origNodes.begin ();
    NODE_LIST_ITERATOR iorigEnd   = origNodes.end   ();
    NODE_LIST_ITERATOR inewBegin  = newNodes.begin  ();
    NODE_LIST_ITERATOR inewEnd    = newNodes.end    ();

    for ( ; iorigBegin != iorigEnd && inewBegin != inewEnd; iorigBegin++, inewBegin++) {
      
      PatriciaTrieNode<S,T>* origNode = *iorigBegin;
      PatriciaTrieNode<S,T>* newNode  = *inewBegin;

      //
      // make some checks that everything went fine
      //

      assert (origNode      != newNode        && 
          origNode->key     == newNode->key     &&
          origNode->bit_index == newNode->bit_index &&
          origNode->data      == newNode->data    );

      //
      // if the original node has backedges:
      // find the correct backedge node in the new trie
      // and wire the children correctly
      //

      if (origNode->left->bit_index < origNode->bit_index)
        newNode->left = newTrie->find_bitindex_node (newTrie->head, origNode->left->bit_index); 
      
      if (origNode->right->bit_index < origNode->bit_index)
        newNode->right = newTrie->find_bitindex_node (newTrie->head, origNode->right->bit_index); 
    
    } // for ( ; iorigBegin != iorigEnd && inewBegin != inewEnd; iorigBegin++, inewBegin++) 
  
  } // if (recursiveHead)

  return newTrie;
}