Browse Source

first commit

mwq 9 months ago
parent
commit
b0a2471dab
100 changed files with 21851 additions and 8 deletions
  1. BIN
      comx_sdk.node/addon-js.rar
  2. BIN
      comx_sdk.node/addon/js_ext_comx_cascade_fill-native-win.node
  3. BIN
      comx_sdk.node/addon/js_ext_comx_cascade_find-native-win.node
  4. BIN
      comx_sdk.node/addon/js_ext_comx_cascade_fix-native-win.node
  5. BIN
      comx_sdk.node/addon/js_ext_comx_cascade_io-native-win.rar
  6. BIN
      comx_sdk.node/addon/js_ext_comx_cascade_test-native-win.node
  7. BIN
      comx_sdk.node/addon/js_ext_comx_ply_io-native-win.node
  8. BIN
      comx_sdk.node/addon/js_ext_comx_resource-native-win.node
  9. BIN
      comx_sdk.node/addon/js_ext_comx_test1-native-win.node
  10. BIN
      comx_sdk.node/addon/js_ext_comx_test_-native-win.node
  11. BIN
      comx_sdk.node/addon/js_ext_comx_ttt-native-win.node
  12. BIN
      comx_sdk.node/addon/js_ext_comx_tttx-native-win.node
  13. BIN
      comx_sdk.node/addon/libonestep.dll
  14. 2 0
      comx_sdk.node/cjh/src/solveMoTai/desktop.ini
  15. 1 1
      comx_sdk.node/data/eslint.rules.json
  16. 1416 0
      comx_sdk.node/include/ModelIO.buffer/BaseIO.h
  17. 474 0
      comx_sdk.node/include/ModelIO.buffer/GTree.h
  18. 45 0
      comx_sdk.node/include/ModelIO.buffer/IgsIO.h
  19. 166 0
      comx_sdk.node/include/ModelIO.buffer/MeshIO_md5.h
  20. 408 0
      comx_sdk.node/include/ModelIO.buffer/ModelIO.h
  21. 148 0
      comx_sdk.node/include/ModelIO.buffer/OccBufferFileIO.h
  22. 44 0
      comx_sdk.node/include/ModelIO.buffer/StpIO.h
  23. 447 0
      comx_sdk.node/include/ModelIO.buffer/json/json-forwards.h
  24. 2375 0
      comx_sdk.node/include/ModelIO.buffer/json/json.h
  25. 447 0
      comx_sdk.node/include/ModelIO.buffer/jsoncpp/json/json-forwards.h
  26. 2375 0
      comx_sdk.node/include/ModelIO.buffer/jsoncpp/json/json.h
  27. 5342 0
      comx_sdk.node/include/ModelIO.buffer/jsoncpp/jsoncpp.cpp
  28. BIN
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/TCL.chm
  29. 23 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/alpha.h
  30. 172 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/associative_tree.h
  31. 285 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/associative_tree.inl
  32. 101 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/basic_tree.h
  33. 93 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/basic_tree.inl
  34. 246 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/child_iterator.h
  35. 225 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/child_node_iterator.h
  36. 308 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_iterator.h
  37. 222 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_iterator.inl
  38. 296 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_node_iterator.h
  39. 221 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_node_iterator.inl
  40. 135 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/multitree.h
  41. 76 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/multitree.inl
  42. 111 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/ordered_iterator.h
  43. 114 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/populateAlphabet.h
  44. 124 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/reverse_iterator.h
  45. 119 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/reverse_node_iterator.h
  46. 283 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/sequential_tree.h
  47. 333 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/sequential_tree.inl
  48. 135 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/tree.h
  49. 76 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/tree.inl
  50. 183 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/unique_tree.h
  51. 445 0
      comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/unique_tree.inl
  52. BIN
      comx_sdk.node/include/ModelIO/BaseIO.rar
  53. 1316 0
      comx_sdk.node/include/ModelIO/BaseIO/BaseIO.h
  54. 110 0
      comx_sdk.node/include/ModelIO/CurveAdaptiveDiscrete.h
  55. 286 0
      comx_sdk.node/include/ModelIO/FaceProperty.h
  56. 309 0
      comx_sdk.node/include/ModelIO/GeoAPIUtil.h
  57. 1 0
      comx_sdk.node/include/ModelIO/ModelDistance.h
  58. 246 0
      comx_sdk.node/include/ModelIO/MurmurHash.h
  59. 76 0
      comx_sdk.node/include/ModelIO/RandomColorGenerator.h
  60. 158 0
      comx_sdk.node/include/ModelIO/TreeLabel.h
  61. 96 0
      comx_sdk.node/include/ModelIO/occ_compatible.h
  62. 459 0
      comx_sdk.node/include/ModelIO/poly_connect_ex.h
  63. 66 0
      comx_sdk.node/js/_model.js
  64. 24 2
      comx_sdk.node/js/dev.js
  65. 27 0
      comx_sdk.node/js/kul_editor_pane.js
  66. 1 0
      comx_sdk.node/js/workArea.cfg.json
  67. 61 5
      comx_sdk.node/kul/toolbarpane_new.kul
  68. 12 0
      comx_sdk.node/node_modules/.bin/browsers
  69. 17 0
      comx_sdk.node/node_modules/.bin/browsers.cmd
  70. 28 0
      comx_sdk.node/node_modules/.bin/browsers.ps1
  71. 12 0
      comx_sdk.node/node_modules/.bin/browserslist
  72. 17 0
      comx_sdk.node/node_modules/.bin/browserslist.cmd
  73. 28 0
      comx_sdk.node/node_modules/.bin/browserslist.ps1
  74. 12 0
      comx_sdk.node/node_modules/.bin/escodegen
  75. 17 0
      comx_sdk.node/node_modules/.bin/escodegen.cmd
  76. 28 0
      comx_sdk.node/node_modules/.bin/escodegen.ps1
  77. 12 0
      comx_sdk.node/node_modules/.bin/esgenerate
  78. 17 0
      comx_sdk.node/node_modules/.bin/esgenerate.cmd
  79. 28 0
      comx_sdk.node/node_modules/.bin/esgenerate.ps1
  80. 12 0
      comx_sdk.node/node_modules/.bin/esparse
  81. 17 0
      comx_sdk.node/node_modules/.bin/esparse.cmd
  82. 28 0
      comx_sdk.node/node_modules/.bin/esparse.ps1
  83. 12 0
      comx_sdk.node/node_modules/.bin/esvalidate
  84. 17 0
      comx_sdk.node/node_modules/.bin/esvalidate.cmd
  85. 28 0
      comx_sdk.node/node_modules/.bin/esvalidate.ps1
  86. 12 0
      comx_sdk.node/node_modules/.bin/extract-zip
  87. 17 0
      comx_sdk.node/node_modules/.bin/extract-zip.cmd
  88. 28 0
      comx_sdk.node/node_modules/.bin/extract-zip.ps1
  89. 12 0
      comx_sdk.node/node_modules/.bin/import-local-fixture
  90. 17 0
      comx_sdk.node/node_modules/.bin/import-local-fixture.cmd
  91. 28 0
      comx_sdk.node/node_modules/.bin/import-local-fixture.ps1
  92. 12 0
      comx_sdk.node/node_modules/.bin/jest
  93. 17 0
      comx_sdk.node/node_modules/.bin/jest.cmd
  94. 28 0
      comx_sdk.node/node_modules/.bin/jest.ps1
  95. 12 0
      comx_sdk.node/node_modules/.bin/jsesc
  96. 17 0
      comx_sdk.node/node_modules/.bin/jsesc.cmd
  97. 28 0
      comx_sdk.node/node_modules/.bin/jsesc.ps1
  98. 12 0
      comx_sdk.node/node_modules/.bin/json5
  99. 17 0
      comx_sdk.node/node_modules/.bin/json5.cmd
  100. 0 0
      comx_sdk.node/node_modules/.bin/json5.ps1

BIN
comx_sdk.node/addon-js.rar


BIN
comx_sdk.node/addon/js_ext_comx_cascade_fill-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_cascade_find-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_cascade_fix-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_cascade_io-native-win.rar


BIN
comx_sdk.node/addon/js_ext_comx_cascade_test-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_ply_io-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_resource-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_test1-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_test_-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_ttt-native-win.node


BIN
comx_sdk.node/addon/js_ext_comx_tttx-native-win.node


BIN
comx_sdk.node/addon/libonestep.dll


+ 2 - 0
comx_sdk.node/cjh/src/solveMoTai/desktop.ini

@@ -0,0 +1,2 @@
+[LocalizedFileNames]
+freetype.dll=@freetype.dll,0

+ 1 - 1
comx_sdk.node/data/eslint.rules.json

@@ -9,7 +9,7 @@
     "no-const-assign": "error",
     "no-constant-condition": "error",
     "no-control-regex": "error",
-    "no-debugger": "error",
+    "no-debugger": "off",
     "no-delete-var": "error",
     "no-dupe-args": "error",
     "no-dupe-class-members": "error",

File diff suppressed because it is too large
+ 1416 - 0
comx_sdk.node/include/ModelIO.buffer/BaseIO.h


+ 474 - 0
comx_sdk.node/include/ModelIO.buffer/GTree.h

@@ -0,0 +1,474 @@
+#ifndef GTREE_H
+#define GTREE_H
+
+#include <vector>
+#include <map>
+#include <iostream>
+
+using namespace std;
+
+enum GTreeNodeType
+{
+	Product,
+	Part
+};
+
+// 通用树节点
+template < typename T >
+class GTreeNode
+{
+public:
+	T value;
+	GTreeNode<T>* parent;
+	vector<GTreeNode<T>*> child;
+	bool m_flag;
+
+	GTreeNode()
+	{
+		parent = NULL;
+		m_flag = false;
+	}
+
+	static GTreeNode<T>* NewNode() // 工厂模式
+	{
+		GTreeNode<T>* ret = new GTreeNode<T>();
+		if (ret != NULL)  // 申请堆空间成功
+		{
+			ret->m_flag = true;
+		}
+
+		return ret;
+	}
+
+	bool add(GTreeNode<T>* node)
+	{
+		child.push_back(node);
+	}
+
+	bool flag()
+	{
+		return m_flag;
+	}
+};
+
+template <typename T>
+class GTree
+{
+public:
+	GTreeNode<T>* m_root;
+	string name;
+
+	GTree() { m_root = GTreeNode<T>::NewNode(); }
+	//插入结点
+	GTreeNode<T>* GetRootNode() { return m_root; }
+
+	string GetName()
+	{
+		return name;
+	}
+
+	void SetName(string _name)
+	{
+		name = _name;
+	}
+
+
+	//基于数据元素值的查找,都是遍历实现的
+	GTreeNode<T>* find(GTreeNode<T>* node, const T& value)const
+	{
+		GTreeNode<T>* ret = NULL;
+		if (node != NULL)
+		{
+			//如果根结点的就是目标结点
+			if (node->value == value)
+			{
+				return node;
+			}
+			else
+			{
+				//遍历根节点的子结点
+				//for (node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
+				//{
+				//	//对每个子子结点进行查找
+				//	ret = find(node->child.current(), value);
+				//}
+
+				for (int i = 0; i < node->child.size(); i++)
+				{
+					//对每个子子结点进行查找
+					ret = find(node->child[i], value);
+				}
+			}
+		}
+		return ret;
+	}
+	//基于结点得查找
+	GTreeNode<T>* find(GTreeNode<T>* node, GTreeNode<T>* obj)const
+	{
+		GTreeNode<T>* ret = NULL;
+		//根结点为目标结点
+		if (node == obj)
+		{
+			return node;
+		}
+		else
+		{
+			if (node != NULL)
+			{
+				//遍历子结点
+				//for (node->child.move(0); !node->child.end() && (ret == NULL); node->child.next())
+				//{
+				//	ret = find(node->child.current(), obj);
+				//}
+
+				for (int i = 0; i < node->child.size(); i++)
+				{
+					ret = find(node->child[i], obj);
+				}
+			}
+		}
+		return ret;
+	}
+
+	void free(GTreeNode<T>* node)
+	{
+		if (node != NULL)
+		{
+			//for (node->child.move(0); !node->child.end(); node->child.next())
+			//{
+			//	free(node->child.current());
+			//}
+
+			for (int i = 0; i < node->child.size(); i++)
+			{
+				free(node->child[i]);
+			}
+
+			if (node->flag())
+			{
+				delete node;
+			}
+		}
+	}
+
+	/*
+	 * 删除操作成员函数的设计要点
+	 *   将被删除结点所代表的子树进行删除
+	 *   删除函数返回一颗堆空间中的树
+	 *   具体返回值为指向树的智能指针对象
+	 */
+	void remove(GTreeNode<T>* node, GTree<T>*& ret)
+	{
+		ret = new GTree<T>();
+
+		if (ret == NULL)
+		{
+			//THROW_EXCEPTION(NoEoughMemoryException, "...");
+		}
+		else
+		{
+			if (root() != node)
+			{
+				//获取删除结点的父结点的子结点链表
+				//LinkList<GTreeNode<T>*>& child = dynamic_cast<GTreeNode<T>*>(node->parent)->child;
+				child.remove(child.find(node)); //从链表中删除结点
+				node->parent = NULL;//结点的父结点置NULL
+			}
+			else
+			{
+				this->m_root = NULL;
+			}
+		}
+	}
+
+	int count(GTreeNode<T>* node)const
+	{
+		int ret = 0;
+		if (node != NULL)
+		{
+			ret = 1;
+			//遍历根结点的子节点
+			for (node->child.move(0); !node->child.end(); node->child.next())
+			{
+				ret += count(node->child.current());//对结点进行统计
+			}
+		}
+
+		return ret;
+	}
+
+	int degree(GTreeNode<T>* node)const
+	{
+		int ret = 0;
+		if (node != NULL)
+		{
+			ret = node->child.length();
+
+			for (node->child.move(0); !node->child.end(); node->child.next())
+			{
+				int d = degree(node->child.current());
+
+				if (ret < d)
+				{
+					ret = d;
+				}
+			}
+		}
+
+		return ret;
+	}
+
+	int height(GTreeNode<T>* node)const
+	{
+		int ret = 0;
+
+		if (node != NULL)
+		{
+			for (node->child.move(0); !node->child.end(); node->child.next())
+			{
+				int h = height(node->child.current());
+
+				if (ret < h)
+				{
+					ret = h;
+				}
+			}
+
+			ret = ret + 1;
+		}
+
+		return ret;
+	}
+
+	bool insert(GTreeNode<T>* node)
+	{
+		bool ret = true;
+
+		if (node != NULL)//当结点不为空时
+		{
+			if (this->m_root == NULL)//如果此时的根结点为空
+			{
+				node->parent = NULL;//node结点就是根结点
+				this->m_root = node;
+			}
+			else
+			{
+				GTreeNode<T>* np = find(node->parent);//在堆空间创建np指向node的父节点
+				if (np != NULL)
+				{
+					GTreeNode<T>* n = dynamic_cast<GTreeNode<T>*>(node);//noded的类型为TreeNode,需要将其强制转换为GTreeNode
+
+					//if (np->child.find(n) < 0)
+					//{
+					//	ret = np->child.insert(n);
+					//}
+					np->child.push_back(n);
+				}
+				else
+				{
+					//THROW_EXCEPTION(InvalidOperationException, "...");
+				}
+			}
+		}
+		else
+		{
+			//THROW_EXCEPTION(InvalidOperationException, "...");
+		}
+
+		return ret;
+	}
+
+	bool insert(const T& value, GTreeNode<T>* parent)
+	{
+		bool ret = true;
+
+		GTreeNode<T>* node = GTreeNode<T>::NewNode();
+
+		if (node != NULL)
+		{
+			node->value = value;
+			node->parent = parent;
+
+			insert(node);
+		}
+		else
+		{
+			//THROW_EXCEPTION(InvalidOperationException, "...");
+		}
+
+		return ret;
+	}
+
+	bool change(const T& value, GTreeNode<T>* node)
+	{
+		bool ret = true;
+
+		if (node != NULL)
+		{
+			node->value = value;
+		}
+		else
+		{
+			//THROW_EXCEPTION(InvalidOperationException, "...");
+		}
+
+		return ret;
+	}
+
+	GTreeNode<T>* add(const T& value, GTreeNode<T>* parent)
+	{
+		GTreeNode<T>* node = GTreeNode<T>::NewNode();
+
+		if (node != NULL)
+		{
+			node->value = value;
+			node->parent = parent;
+
+			insert(node);
+		}
+		else
+		{
+			//THROW_EXCEPTION(InvalidOperationException, "...");
+		}
+
+		return node;
+	}
+
+	//删除结点
+	//SharedPointer< Tree<T> > remove(const T& value)
+	//{
+	//	GTree<T>* ret = NULL;
+
+	//	GTreeNode<T>* node = find(value);
+
+	//	if (node != NULL)
+	//	{
+	//		remove(node, ret);
+	//	}
+	//	else
+	//	{
+	//		THROW_EXCEPTION(InvalidOperationException, "...");
+	//	}
+
+	//	return ret;
+	//}
+
+	//SharedPointer< Tree<T> > remove(TreeNode<T>* node)
+	//{
+	//	GTree<T>* ret = NULL;
+	//	node = find(node);
+
+	//	if (node != NULL)
+	//	{
+	//		remove(dynamic_cast<GTreeNode<T>*>(node), ret);
+	//	}
+	//	else
+	//	{
+	//		THROW_EXCEPTION(InvalidOperationException, "...");
+	//	}
+
+	//	return NULL;
+	//}
+
+	//查找结点
+	GTreeNode<T>* find(const T& value)const
+	{
+		return find(root(), value);
+	}
+
+	GTreeNode<T>* find(GTreeNode<T>* node)const
+	{
+		return find(root(), dynamic_cast<GTreeNode<T>*>(node));//强制类型转换将TreeNode类型转换为GTreeNode类型
+	}//root对应的root的类型也应该一样
+
+	//根结点访问函数
+	GTreeNode<T>* root()const
+	{
+		return dynamic_cast<GTreeNode<T>*>(this->m_root);
+	}
+
+	//树的度访问函数
+	int degree()const
+	{
+		return degree(root());
+	}
+
+	//树的高度访问函数
+	int height()const
+	{
+		return height(root());
+	}
+
+	//树的结点数目访问函数
+	int count()const
+	{
+		return count(root());
+	}
+
+	//清空树
+	void clear()
+	{
+		free(root());
+		this->m_root = NULL;
+	}
+
+	//树中结点的遍历
+	//树是一种非线性的数据结构,遍历树中结点可以采用游标的方式。
+	//A、在树中定义一个游标(GTreeNode<T>* node)
+	//B、遍历开始前将游标指向根结点
+	//C、获取游标指向的数据元素
+	//D、通过结点中的child成员移动游标
+
+	//bool begin()
+	//{
+	//	bool ret = (root() != NULL);
+
+	//	if (ret)
+	//	{
+	//		m_queue.clear();//清空队列
+	//		m_queue.add(root());//将根结点加入队列
+	//	}
+	//	return ret;
+	//}
+
+	//bool end()
+	//{
+	//	return (m_queue.length() == 0);
+	//}
+
+	//bool next()
+	//{
+	//	bool ret = (m_queue.length() > 0);
+	//	{
+	//		GTreeNode<T>* node = m_queue.front();
+	//		m_queue.remove();//队头元素出队列
+	//		//将队头元素的子节点入队
+	//		for (node->child.move(0); !node->child.end(); node->child.next())
+	//		{
+	//			m_queue.add(node->child.current());
+	//		}
+
+	//		return ret;
+	//	}
+	//}
+
+	//T current()
+	//{
+	//	if (!end())
+	//	{
+	//		return m_queue.front()->value;
+	//	}
+	//	else
+	//	{
+	//		THROW_EXCEPTION(InvalidOperationException, "...");
+	//	}
+	//}
+
+	~GTree()
+	{
+		clear();
+	}
+};
+
+
+#endif

+ 45 - 0
comx_sdk.node/include/ModelIO.buffer/IgsIO.h

@@ -0,0 +1,45 @@
+#ifndef IGSIO_H
+#define IGSIO_H
+
+#include "BaseIO.h"
+
+#include <IGESCAFControl_Reader.hxx>
+#include <BinXCAFDrivers.hxx>
+#include <XCAFApp_Application.hxx>
+
+class IgsIO : public BaseIO
+{
+public:
+	IgsIO() {}
+	virtual void Read(string fileName);
+};
+
+inline void IgsIO::Read(string fileName)
+{
+	cout << "ReadStep fileName: " << fileName << endl;
+
+	Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
+	BinXCAFDrivers::DefineFormat(anApp);
+	anApp->NewDocument("BinXCAF", doc);
+
+	IGESCAFControl_Reader aStepReader;
+	aStepReader.SetColorMode(true);
+	aStepReader.SetNameMode(true);
+
+	aStepReader.ReadFile(fileName.c_str());
+
+	aStepReader.Transfer(doc);
+
+#ifdef OCCTEST
+
+	PCDM_StoreStatus sstate = anApp->SaveAs(doc, "F:/test.xbf");
+	if (sstate != PCDM_SS_OK)
+	{
+		cout << "Save Failed" << endl;
+	}
+#endif	
+
+	cout << "ReadStep fileName Successed" << endl;
+}
+
+#endif

+ 166 - 0
comx_sdk.node/include/ModelIO.buffer/MeshIO_md5.h

@@ -0,0 +1,166 @@
+#ifndef MD5_CALCULATOR_H
+#define MD5_CALCULATOR_H
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <iomanip>
+
+// 定义一些常量
+const unsigned int S[4][4] = {
+    {7, 12, 17, 22},
+    {5,  9, 14, 20},
+    {4, 11, 16, 23},
+    {6, 10, 15, 21}
+};
+const unsigned int K[64] = {
+    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+    0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+    0xf61e2562, 0xc040b340, 0x2678e6fd, 0xa2bfe8a1,
+    0xc76c51a3, 0x71c337dd, 0x1f83d9ab, 0x29adceea,
+    0xb00327c8, 0x98df8b00, 0xef1f191e, 0xe39492a6,
+    0x9d618830, 0x498ea3e5, 0x3b10d28a, 0xd15d2c09,
+    0xf4d50d87, 0x391c0cb3, 0x43186745, 0xa53a76d8,
+    0x500c6d83, 0x7d850099, 0x2441453b, 0x0d95748f,
+    0x6d9d6122, 0x92722c85, 0x223a8025, 0x53b0a992,
+    0x7479632e, 0x0b3e2b8a, 0x40652319, 0x7766a0ab,
+    0x62950c60, 0x5a9fe429, 0x106aa070, 0x32d2efba,
+    0x03601104, 0xd6990624, 0x983e5152, 0x597f299c,
+    0x2b040329, 0x86cb3077, 0x60902e59, 0x74c4756a,
+    0xa4904230, 0xf75095dd, 0x1983d9ab, 0x076295c7
+};
+const unsigned int A0 = 0x67452301;
+const unsigned int B0 = 0xefcdab89;
+const unsigned int C0 = 0x98badcfe;
+const unsigned int D0 = 0x10325476;
+
+inline unsigned int leftRotate(unsigned int x, unsigned int n) {
+        return (x << n) | (x >> (32 - n));
+}
+
+inline unsigned int F(unsigned int b, unsigned int c, unsigned int d) {
+        return (b & c) | ((~b) & d);
+}
+
+inline unsigned int G(unsigned int b, unsigned int c, unsigned int d) {
+        return (b & d) | (c & (~d));
+}
+
+inline unsigned int H(unsigned int b, unsigned int c, unsigned int d) {
+        return b ^ c ^ d;
+}
+
+inline unsigned int I(unsigned int b, unsigned int c, unsigned int d) {
+        return c ^ (b | (~d));
+}
+
+inline void md5ProcessBlock(unsigned int* M, unsigned int& A, unsigned int& B, unsigned int& C, unsigned int& D) {
+        unsigned int a = A;
+        unsigned int b = B;
+        unsigned int c = C;
+        unsigned int d = D;
+
+        for (int i = 0; i < 64; ++i) {
+                unsigned int f, g;
+                if (i < 16) {
+                        f = F(b, c, d);
+                        g = i;
+                }
+                else if (i < 32) {
+                        f = G(b, c, d);
+                        g = (5 * i + 1) % 16;
+                }
+                else if (i < 48) {
+                        f = H(b, c, d);
+                        g = (3 * i + 5) % 16;
+                }
+                else {
+                        f = I(b, c, d);
+                        g = (7 * i) % 16;
+                }
+
+                unsigned int temp = d;
+                d = c;
+                c = b;
+                b = leftRotate(a + f + K[i] + M[g], S[i / 16][i % 4]) + b;
+                a = temp;
+        }
+
+        A += a;
+        B += b;
+        C += c;
+        D += d;
+}
+
+inline void padMessage(const unsigned char* originalMessage, unsigned int originalLength, unsigned char*& paddedMessage, unsigned int& paddedLength) {
+        // 计算填充后的长度
+        paddedLength = originalLength;
+        while (paddedLength % 64 != 56) {
+                paddedLength++;
+        }
+        paddedLength += 8;
+
+        // 分配填充后的数据内存
+        paddedMessage = new unsigned char[paddedLength];
+        // 复制原始数据
+        for (unsigned int i = 0; i < originalLength; ++i) {
+                paddedMessage[i] = originalMessage[i];
+        }
+        // 填充1
+        paddedMessage[originalLength] = 0x80;
+        // 填充0
+        for (unsigned int i = originalLength + 1; i < paddedLength - 8; ++i) {
+                paddedMessage[i] = 0x00;
+        }
+        // 添加原始数据长度(以位为单位)
+        unsigned long long bitLength = originalLength * 8;
+        for (int i = 0; i < 8; ++i) {
+                paddedMessage[paddedLength - 8 + i] = (bitLength >> (8 * (7 - i))) & 0xFF;
+        }
+}
+
+inline std::string calculateMD5(const std::string& fileName) {
+        std::ifstream file(fileName, std::ios::binary);
+        if (!file) {
+                std::cerr << "无法打开文件: " << fileName << std::endl;
+                return "";
+        }
+
+        // 读取文件内容到内存
+        file.seekg(0, std::ios::end);
+        unsigned int originalLength = file.tellg();
+        file.seekg(0, std::ios::beg);
+        unsigned char* originalMessage = new unsigned char[originalLength];
+        file.read(reinterpret_cast<char*>(originalMessage), originalLength);
+
+        // 填充数据
+        unsigned char* paddedMessage;
+        unsigned int paddedLength;
+        padMessage(originalMessage, originalLength, paddedMessage, paddedLength);
+
+        // 初始化MD5寄存器
+        unsigned int A = A0;
+        unsigned int B = B0;
+        unsigned int C = C0;
+        unsigned int D = D0;
+
+        // 处理分组
+        for (unsigned int i = 0; i < paddedLength; i += 64) {
+                unsigned int* M = reinterpret_cast<unsigned int*>(paddedMessage + i);
+                md5ProcessBlock(M, A, B, C, D);
+        }
+
+        // 释放内存
+        delete[] originalMessage;
+        delete[] paddedMessage;
+
+        // 构建MD5结果字符串
+        std::stringstream ss;
+        ss << std::hex << std::setfill('0');
+        ss << std::setw(8) << A << std::setw(8) << B << std::setw(8) << C << std::setw(8) << D;
+        return ss.str();
+}
+
+#endif

+ 408 - 0
comx_sdk.node/include/ModelIO.buffer/ModelIO.h

@@ -0,0 +1,408 @@
+#ifndef MODELIO_H
+#define MODELIO_H
+
+#include "BaseIO.h"
+
+#include <BinXCAFDrivers.hxx>
+#include <XCAFApp_Application.hxx>
+
+#include <TDF_Label.hxx>
+#include <TDF_Tool.hxx>
+#include <TDF_Attribute.hxx>
+#include <TDF_LabelMap.hxx>
+#include <TDF_LabelSequence.hxx>
+#include <IFSelect_ReturnStatus.hxx>
+#include <Interface_Static.hxx>
+#include <Interface_EntityIterator.hxx>
+#include <Interface_Check.hxx>
+#include <Standard_CString.hxx>
+#include <Standard_Boolean.hxx>
+#include <Standard_Integer.hxx>
+#include <Standard_OStream.hxx>
+
+#include <XCAFDoc_Color.hxx>
+
+#include <STEPControl_StepModelType.hxx>
+#include <UnitsMethods.hxx>
+#include <Prs3d_Drawer.hxx>
+
+#include <IGESCAFControl_Reader.hxx>
+#include <IGESCAFControl_Writer.hxx>
+
+#include <STEPCAFControl_Reader.hxx>
+#include <STEPCAFControl_Writer.hxx>
+
+#include <RWGltf_CafReader.hxx>
+#include <RWGltf_CafWriter.hxx>
+
+#include <StlAPI_Writer.hxx>
+#include <StlAPI_Reader.hxx>
+
+enum GeomType
+{
+	GeomSTP,
+	GeomIGS,
+	GeomSTL,
+	GeomBREP,
+	GeomGLTF
+};
+
+class ModelIO : public BaseIO
+{
+public:
+	ModelIO() {}
+	bool Read(const string &fileName, const GeomType &modelType);
+	bool Write(const string &fileName, const GeomType &modelType);
+
+private:
+	bool ReadIGS(const string &fileName);
+	bool ReadSTP(const string &fileName);
+	bool ReadBREP(const string &filename);
+	bool ReadSTL(const string &filename);
+	bool ReadGLTF(const string &filename);
+
+	bool WriteSTP(const string &fileName);
+	bool WriteIGS(const string &fileName);
+	bool WriteBREP(const string &fileName);
+	bool WriteSTL(const string &fileName);
+	bool WriteGLTF(const string &fileName);
+
+	GeomType modelFormat;
+};
+
+inline bool ModelIO::Read(const string &fileName, const GeomType &modelType)
+{
+	modelFormat = modelType;
+
+	switch (modelType)
+	{
+	case GeomSTP:
+		return ReadSTP(fileName);
+	case GeomIGS:
+		return ReadIGS(fileName);
+	case GeomSTL:
+		return ReadSTL(fileName);
+	case GeomBREP:
+		return ReadBREP(fileName);
+	case GeomGLTF:
+		return ReadGLTF(fileName);
+	default:
+		break;
+	}
+
+	return false;
+}
+
+inline bool ModelIO::Write(const string &fileName, const GeomType &modelType)
+{
+	switch (modelType)
+	{
+	case GeomSTP:
+		return WriteSTP(fileName);
+	case GeomIGS:
+		return WriteIGS(fileName);
+	case GeomSTL:
+		return WriteSTL(fileName);
+	case GeomBREP:
+		return WriteBREP(fileName);
+	case GeomGLTF:
+		return WriteGLTF(fileName);
+	default:
+		break;
+	}
+
+	return false;
+}
+
+inline bool ModelIO::ReadIGS(const string &fileName)
+{
+	IGESCAFControl_Reader aIgesReader;
+	aIgesReader.SetColorMode(true);
+	aIgesReader.SetNameMode(true);
+
+	IFSelect_ReturnStatus status = aIgesReader.ReadFile(fileName.c_str());
+
+	Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
+	BinXCAFDrivers::DefineFormat(anApp);
+	anApp->NewDocument("BinXCAF", doc);
+
+	if (status == IFSelect_RetDone)
+	{
+		aIgesReader.Transfer(doc);
+		return true;
+	}
+
+	return false;
+}
+
+inline bool ModelIO::ReadSTP(const string &fileName)
+{
+
+	Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
+	BinXCAFDrivers::DefineFormat(anApp);
+	anApp->NewDocument("BinXCAF", doc);
+
+	STEPCAFControl_Reader aStepReader;
+	aStepReader.SetColorMode(true);
+	aStepReader.SetNameMode(true);
+
+	IFSelect_ReturnStatus status = aStepReader.ReadFile(fileName.c_str());
+
+
+	//--------------
+	//TopoDS_Shape shape_Step;
+
+	//STEPControl_Reader aReader_Step = aStepReader.Reader();
+	//	int j = 1;
+
+	//for (Standard_Integer i = 1; i <= aReader_Step.NbRootsForTransfer(); i++)
+	//	aReader_Step.TransferRoot(i);
+	//for (Standard_Integer i = 1; i <= aReader_Step.NbShapes(); i++)
+	//	shape_Step = aReader_Step.Shape(i);
+
+	//TopTools_IndexedMapOfShape solids_map, shells_map, faces_map, wires_map, edges_map, vertices_map;
+	//TopExp_Explorer exp_solids, exp_shells, exp_faces, exp_wires, exp_edges, exp_vertices;
+	//for (exp_faces.Init(shape_Step, TopAbs_FACE); exp_faces.More(); exp_faces.Next())
+	//{
+	//	TopoDS_Face face = TopoDS::Face(exp_faces.Current().Composed(shape_Step.Orientation()));
+
+	//	cout << face.HashCode()
+
+	//	j++;
+	//}
+
+	//--------------
+
+	if (status == IFSelect_RetDone)
+	{
+		aStepReader.Transfer(doc);
+		return true;
+	}
+
+	return false;
+}
+
+inline bool ModelIO::ReadBREP(const string &filename)
+{
+	TopoDS_Shape aShape;
+	BRep_Builder aBuilder;
+
+	if (!BRepTools::Read(aShape, filename.c_str(), aBuilder))
+	{
+		return false;
+	}	
+
+	doc = new TDocStd_Document("BRep");
+
+	Handle(XCAFDoc_ShapeTool) ST = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
+
+	ST->AddShape(aShape);
+
+	return true;
+}
+
+inline bool ModelIO::ReadSTL(const string &filename)
+{
+	TopoDS_Shape aShape;
+
+	StlAPI_Reader anStlReader;
+
+	if (!anStlReader.Read(aShape, filename.c_str()))
+	{
+		return false;
+	}
+
+	doc = new TDocStd_Document("STL");
+
+	Handle(XCAFDoc_ShapeTool) ST = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
+	Handle(XCAFDoc_ColorTool) CT = XCAFDoc_DocumentTool::ColorTool(doc->Main());
+	Quantity_ColorRGBA aColor(0.644479692f, 0.644479692f, 1.00000000f, 1.00000000f);
+
+	TDF_Label aLabel = ST->AddShape(aShape);
+	CT->SetColor(aShape, aColor, XCAFDoc_ColorSurf);
+
+	TDataStd_Name::Set(aLabel, "STL_Shape");
+
+	return true;
+}
+
+inline bool ModelIO::ReadGLTF(const string &filename)
+{
+	Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
+	BinXCAFDrivers::DefineFormat(anApp);
+	anApp->NewDocument("BinXCAF", doc);
+
+	RWGltf_CafReader aReader;
+	Standard_Real aSystemUnitFactor = UnitsMethods::GetCasCadeLengthUnit() * 0.001;
+	aReader.SetSystemLengthUnit(aSystemUnitFactor);
+	aReader.SetSystemCoordinateSystem(RWMesh_CoordinateSystem_Zup);
+	aReader.SetDocument(doc);
+	aReader.SetParallel(Standard_True);
+	Message_ProgressRange theProgress;
+
+	if (aReader.Perform(filename.c_str(), theProgress))
+	{
+		Handle(XCAFDoc_ColorTool) CT = XCAFDoc_DocumentTool::ColorTool(doc->Main());
+		Quantity_ColorRGBA aColor(0.644479692, 0.644479692, 1.00000000, 1.00000000);
+		CT->SetColor(doc->Main(), aColor, XCAFDoc_ColorSurf);
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+// ------------------------------------------
+// Write Files
+// ------------------------------------------
+inline bool ModelIO::WriteSTP(const string &fileName)
+{
+	if (modelFormat == GeomGLTF)
+	{
+		return false;
+	}
+
+	STEPControl_StepModelType mode = STEPControl_AsIs;
+
+	STEPCAFControl_Writer aWriter;
+	aWriter.SetColorMode(true);
+	aWriter.SetNameMode(true);
+
+	// Translating document (conversion) to STEP
+	if (!aWriter.Transfer(doc, mode)) {
+		return false;
+	}
+	// Writing the File
+	IFSelect_ReturnStatus status = aWriter.Write(fileName.c_str());
+
+	// ¼ì²éÊÇ·ñ³É¹¦Ð´Èë
+	if (status != IFSelect_RetDone) {
+		return false;		
+	}
+
+	return true;
+}
+inline bool ModelIO::WriteIGS(const string &fileName)
+{
+	if (modelFormat == GeomGLTF)
+	{
+		return false;
+	}
+
+	IGESCAFControl_Writer aWriter;
+	aWriter.SetColorMode(true);
+	aWriter.SetNameMode(true);
+
+	return aWriter.Perform(doc, fileName.c_str());
+}
+
+inline bool ModelIO::WriteBREP(const string &fileName)
+{
+	Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
+
+	TDF_LabelSequence aRootLabels;
+	aShapeTool->GetFreeShapes(aRootLabels);
+
+	TopoDS_Compound aCompound;
+	BRep_Builder    aBuildTool;
+	aBuildTool.MakeCompound(aCompound);
+	for (TDF_LabelSequence::Iterator aRootIter(aRootLabels); aRootIter.More(); aRootIter.Next())
+	{
+		const TDF_Label& aRootLabel = aRootIter.Value();
+		TopoDS_Shape aRootShape;
+		if (XCAFDoc_ShapeTool::GetShape(aRootLabel, aRootShape))
+		{
+			aBuildTool.Add(aCompound, aRootShape);
+		}
+	}
+
+	return BRepTools::Write(aCompound, fileName.c_str());
+}
+
+
+inline bool ModelIO::WriteSTL(const string &fileName)
+{
+	cout << "WriteSTL " << endl;
+	Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
+
+	TDF_LabelSequence aRootLabels;
+	aShapeTool->GetFreeShapes(aRootLabels);
+
+	TopoDS_Compound aCompound;
+	BRep_Builder    aBuildTool;
+	aBuildTool.MakeCompound(aCompound);
+	for (TDF_LabelSequence::Iterator aRootIter(aRootLabels); aRootIter.More(); aRootIter.Next())
+	{
+		const TDF_Label& aRootLabel = aRootIter.Value();
+		TopoDS_Shape aRootShape;
+		if (XCAFDoc_ShapeTool::GetShape(aRootLabel, aRootShape))
+		{
+			aBuildTool.Add(aCompound, aRootShape);
+		}
+	}
+
+	// perform meshing
+	Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer(); // holds visualization defaults
+	BRepMesh_IncrementalMesh anAlgo;
+	anAlgo.ChangeParameters().Deflection = 0.2;
+	anAlgo.ChangeParameters().Angle = 20.0 * M_PI / 180.0; // 20 degrees
+	anAlgo.ChangeParameters().InParallel = true;
+	anAlgo.SetShape(aCompound);
+	anAlgo.Perform();
+
+	
+
+	StlAPI_Writer anStlWriter;
+	//anStlWriter.ASCIIMode() = false;
+
+	cout << "Start Writing STL." << endl;
+
+	if (anStlWriter.Write(aCompound, fileName.c_str()))
+	{
+		return true;
+	}
+	return false;
+}
+
+inline bool ModelIO::WriteGLTF(const string &fileName)
+{
+	Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
+
+	TDF_LabelSequence aRootLabels;
+	aShapeTool->GetFreeShapes(aRootLabels);
+
+	TopoDS_Compound aCompound;
+	BRep_Builder    aBuildTool;
+	aBuildTool.MakeCompound(aCompound);
+	for (TDF_LabelSequence::Iterator aRootIter(aRootLabels); aRootIter.More(); aRootIter.Next())
+	{
+		const TDF_Label& aRootLabel = aRootIter.Value();
+		TopoDS_Shape aRootShape;
+		if (XCAFDoc_ShapeTool::GetShape(aRootLabel, aRootShape))
+		{
+			aBuildTool.Add(aCompound, aRootShape);
+		}
+	}
+
+	// perform meshing
+	Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer(); // holds visualization defaults
+	BRepMesh_IncrementalMesh anAlgo;
+	anAlgo.ChangeParameters().Deflection = 0.2;
+	anAlgo.ChangeParameters().Angle = 20.0 * M_PI / 180.0; // 20 degrees
+	anAlgo.ChangeParameters().InParallel = true;
+	anAlgo.SetShape(aCompound);
+	anAlgo.Perform();
+
+	TColStd_IndexedDataMapOfStringString aMetadata;
+	Message_ProgressRange theProgress;
+	RWGltf_CafWriter aGltfWriter(fileName.c_str(), true);
+	// STEP reader translates into mm units by default
+	aGltfWriter.ChangeCoordinateSystemConverter().SetInputLengthUnit(0.001);
+	aGltfWriter.ChangeCoordinateSystemConverter().SetInputCoordinateSystem(RWMesh_CoordinateSystem_Zup);
+	if (aGltfWriter.Perform(doc, aMetadata, theProgress))
+	{
+		return true;
+	}
+	return false;
+}
+#endif

+ 148 - 0
comx_sdk.node/include/ModelIO.buffer/OccBufferFileIO.h

@@ -0,0 +1,148 @@
+#ifndef OCC_BUFFER_FILE_IO_H
+#define OCC_BUFFER_FILE_IO_H
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <set>
+#include <string>
+
+struct occ_perform_buffer_t {
+        std::vector<double> points;
+        std::vector<double> normals;
+        std::vector<int> elements;
+        std::set<std::vector<int>> edges;
+};
+
+// 写结构体数组和MD5字符串到文件,成功返回true,失败返回false
+inline bool writeOccPerformBuffer(const std::vector<occ_perform_buffer_t>& buffers, const std::string& md5, const char* fileName) {
+        try {
+                std::ofstream outFile(fileName, std::ios::binary);
+                if (outFile) {
+                        // 写入结构体数组大小
+                        size_t sizeBuffers = buffers.size();
+                        outFile.write(reinterpret_cast<const char*>(&sizeBuffers), sizeof(sizeBuffers));
+
+                        for (const auto& buffer : buffers) {
+                                // 写入points向量大小
+                                size_t sizePoints = buffer.points.size();
+                                outFile.write(reinterpret_cast<const char*>(&sizePoints), sizeof(sizePoints));
+                                // 写入points数据
+                                outFile.write(reinterpret_cast<const char*>(buffer.points.data()), buffer.points.size() * sizeof(double));
+
+                                // 写入normals向量大小
+                                size_t sizeNormals = buffer.normals.size();
+                                outFile.write(reinterpret_cast<const char*>(&sizeNormals), sizeof(sizeNormals));
+                                // 写入normals数据
+                                outFile.write(reinterpret_cast<const char*>(buffer.normals.data()), buffer.normals.size() * sizeof(double));
+
+                                // 写入elements向量大小
+                                size_t sizeElements = buffer.elements.size();
+                                outFile.write(reinterpret_cast<const char*>(&sizeElements), sizeof(sizeElements));
+                                // 写入elements数据
+                                outFile.write(reinterpret_cast<const char*>(buffer.elements.data()), buffer.elements.size() * sizeof(int));
+
+                                // 写入edges集合大小
+                                size_t sizeEdges = buffer.edges.size();
+                                outFile.write(reinterpret_cast<const char*>(&sizeEdges), sizeof(sizeEdges));
+                                // 写入edges数据
+                                for (const auto& edge : buffer.edges) {
+                                        // 写入每个边向量的大小
+                                        size_t edgeSize = edge.size();
+                                        outFile.write(reinterpret_cast<const char*>(&edgeSize), sizeof(edgeSize));
+                                        // 写入边向量的数据
+                                        outFile.write(reinterpret_cast<const char*>(edge.data()), edge.size() * sizeof(int));
+                                }
+                        }
+
+                        // 写入MD5字符串长度
+                        size_t md5Size = md5.length();
+                        outFile.write(reinterpret_cast<const char*>(&md5Size), sizeof(md5Size));
+                        // 写入MD5字符串数据
+                        outFile.write(md5.c_str(), md5.length());
+
+                        outFile.close();
+                        return true;
+                }
+                else {
+                        std::cerr << "Failed to open the file for writing: " << fileName << std::endl;
+                        return false;
+                }
+        }
+        catch (const std::exception& e) {
+                std::cerr << "An exception occurred while writing the file: " << e.what() << std::endl;
+                return false;
+        }
+}
+
+// 从文件读取结构体数组和MD5字符串,成功返回true,失败返回false
+inline bool readOccPerformBuffer(std::vector<occ_perform_buffer_t>& buffers, std::string& md5, const char* fileName) {
+        try {
+                std::ifstream inFile(fileName, std::ios::binary);
+                if (inFile) {
+                        // 读取结构体数组大小
+                        size_t sizeBuffers;
+                        inFile.read(reinterpret_cast<char*>(&sizeBuffers), sizeof(sizeBuffers));
+                        buffers.resize(sizeBuffers);
+
+                        for (auto& buffer : buffers) {
+                                // 读取points向量大小
+                                size_t sizePoints;
+                                inFile.read(reinterpret_cast<char*>(&sizePoints), sizeof(sizePoints));
+                                buffer.points.resize(sizePoints);
+                                // 读取points数据
+                                inFile.read(reinterpret_cast<char*>(buffer.points.data()), buffer.points.size() * sizeof(double));
+
+                                // 读取normals向量大小
+                                size_t sizeNormals;
+                                inFile.read(reinterpret_cast<char*>(&sizeNormals), sizeof(sizeNormals));
+                                buffer.normals.resize(sizeNormals);
+                                // 读取normals数据
+                                inFile.read(reinterpret_cast<char*>(buffer.normals.data()), buffer.normals.size() * sizeof(double));
+
+                                // 读取elements向量大小
+                                size_t sizeElements;
+                                inFile.read(reinterpret_cast<char*>(&sizeElements), sizeof(sizeElements));
+                                buffer.elements.resize(sizeElements);
+                                // 读取elements数据
+                                inFile.read(reinterpret_cast<char*>(buffer.elements.data()), buffer.elements.size() * sizeof(int));
+
+                                // 读取edges集合大小
+                                size_t sizeEdges;
+                                inFile.read(reinterpret_cast<char*>(&sizeEdges), sizeof(sizeEdges));
+                                for (size_t i = 0; i < sizeEdges; ++i) {
+                                        // 读取每个边向量的大小
+                                        size_t edgeSize;
+                                        inFile.read(reinterpret_cast<char*>(&edgeSize), sizeof(edgeSize));
+                                        std::vector<int> edge(edgeSize);
+                                        // 读取边向量的数据
+                                        inFile.read(reinterpret_cast<char*>(edge.data()), edge.size() * sizeof(int));
+                                        buffer.edges.insert(edge);
+                                }
+                        }
+
+                        // 读取MD5字符串长度
+                        size_t md5Size;
+                        inFile.read(reinterpret_cast<char*>(&md5Size), sizeof(md5Size));
+                        // 读取MD5字符串数据
+                        char* md5Str = new char[md5Size + 1];
+                        inFile.read(md5Str, md5Size);
+                        md5Str[md5Size] = '\0';
+                        md5 = md5Str;
+                        delete[] md5Str;
+
+                        inFile.close();
+                        return true;
+                }
+                else {
+                        std::cerr << "Failed to open the file for reading: " << fileName << std::endl;
+                        return false;
+                }
+        }
+        catch (const std::exception& e) {
+                std::cerr << "An exception occurred while reading the file: " << e.what() << std::endl;
+                return false;
+        }
+}
+
+#endif#pragma once

+ 44 - 0
comx_sdk.node/include/ModelIO.buffer/StpIO.h

@@ -0,0 +1,44 @@
+#ifndef STPIO_H
+#define STPIO_H
+
+#include "BaseIO.h"
+
+#include <STEPCAFControl_Reader.hxx>
+#include <STEPCAFControl_Writer.hxx>
+#include <BinXCAFDrivers.hxx>
+#include <XCAFApp_Application.hxx>
+
+class StpIO : public BaseIO
+{
+public:
+	StpIO(){}
+	virtual void Read(string fileName);
+};
+
+inline void StpIO::Read(string fileName)
+{
+
+	Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
+	BinXCAFDrivers::DefineFormat(anApp);
+	anApp->NewDocument("BinXCAF", doc);
+
+	STEPCAFControl_Reader aStepReader;
+	aStepReader.SetColorMode(true);
+	aStepReader.SetNameMode(true);
+
+	aStepReader.ReadFile(fileName.c_str());
+
+	aStepReader.Transfer(doc);
+
+#ifdef OCCTEST
+
+	PCDM_StoreStatus sstate = anApp->SaveAs(doc, "F:/test.xbf");
+	if (sstate != PCDM_SS_OK)
+	{
+		cout << "Save Failed" << endl;
+	}
+#endif	
+
+}
+
+#endif

+ 447 - 0
comx_sdk.node/include/ModelIO.buffer/json/json-forwards.h

@@ -0,0 +1,447 @@
+/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json-forwards.h"
+/// This header provides forward declaration for all JsonCpp types.
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation,
+tests and demonstration applications, are licensed under the following
+conditions...
+
+Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
+jurisdictions which recognize such a disclaimer. In such jurisdictions,
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
+The JsonCpp Authors, and is released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this
+software may choose to accept it either as 1) Public Domain, 2) under the
+conditions of the MIT License (see below), or 3) under the terms of dual
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
+# define JSON_FORWARD_AMALGAMATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgamated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGAMATION
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+#ifndef JSON_VERSION_H_INCLUDED
+#define JSON_VERSION_H_INCLUDED
+
+// Note: version must be updated in three places when doing a release. This
+// annoying process ensures that amalgamate, CMake, and meson all report the
+// correct version.
+// 1. /meson.build
+// 2. /include/json/version.h
+// 3. /CMakeLists.txt
+// IMPORTANT: also update the SOVERSION!!
+
+#define JSONCPP_VERSION_STRING "1.9.5"
+#define JSONCPP_VERSION_MAJOR 1
+#define JSONCPP_VERSION_MINOR 9
+#define JSONCPP_VERSION_PATCH 5
+#define JSONCPP_VERSION_QUALIFIER
+#define JSONCPP_VERSION_HEXA                                                   \
+  ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) |             \
+   (JSONCPP_VERSION_PATCH << 8))
+
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
+#endif // JSON_VERSION_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_ALLOCATOR_H_INCLUDED
+#define JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+#pragma pack(push)
+#pragma pack()
+
+namespace Json {
+template <typename T> class SecureAllocator {
+public:
+  // Type definitions
+  using value_type = T;
+  using pointer = T*;
+  using const_pointer = const T*;
+  using reference = T&;
+  using const_reference = const T&;
+  using size_type = std::size_t;
+  using difference_type = std::ptrdiff_t;
+
+  /**
+   * Allocate memory for N items using the standard allocator.
+   */
+  pointer allocate(size_type n) {
+    // allocate using "global operator new"
+    return static_cast<pointer>(::operator new(n * sizeof(T)));
+  }
+
+  /**
+   * Release memory which was allocated for N items at pointer P.
+   *
+   * The memory block is filled with zeroes before being released.
+   */
+  void deallocate(pointer p, size_type n) {
+    // memset_s is used because memset may be optimized away by the compiler
+    memset_s(p, n * sizeof(T), 0, n * sizeof(T));
+    // free using "global operator delete"
+    ::operator delete(p);
+  }
+
+  /**
+   * Construct an item in-place at pointer P.
+   */
+  template <typename... Args> void construct(pointer p, Args&&... args) {
+    // construct using "placement new" and "perfect forwarding"
+    ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
+  }
+
+  size_type max_size() const { return size_t(-1) / sizeof(T); }
+
+  pointer address(reference x) const { return std::addressof(x); }
+
+  const_pointer address(const_reference x) const { return std::addressof(x); }
+
+  /**
+   * Destroy an item in-place at pointer P.
+   */
+  void destroy(pointer p) {
+    // destroy using "explicit destructor"
+    p->~T();
+  }
+
+  // Boilerplate
+  SecureAllocator() {}
+  template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
+  template <typename U> struct rebind { using other = SecureAllocator<U>; };
+};
+
+template <typename T, typename U>
+bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+  return true;
+}
+
+template <typename T, typename U>
+bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+  return false;
+}
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#endif // JSON_ALLOCATOR_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+#include <cstddef>
+#include <cstdint>
+#include <istream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+// Temporary, tracked for removal with issue #982.
+#ifndef JSON_USE_NULLREF
+#define JSON_USE_NULLREF 1
+#endif
+
+/// If defined, indicates that the source file is amalgamated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgamated header.
+// #define JSON_IS_AMALGAMATION
+
+// Export macros for DLL visibility
+#if defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#elif defined(__GNUC__) || defined(__clang__)
+#define JSON_API __attribute__((visibility("default")))
+#endif // if defined(_MSC_VER)
+
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_DLL_BUILD
+
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1800
+#error                                                                         \
+    "ERROR:  Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+// As recommended at
+// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
+                                              const char* format, ...);
+#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
+#else
+#define jsoncpp_snprintf std::snprintf
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
+// C++11 should be used directly in JSONCPP.
+#define JSONCPP_OVERRIDE override
+
+#ifdef __clang__
+#if __has_extension(attribute_deprecated_with_message)
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
+#endif
+#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
+#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
+#endif                  // GNUC version
+#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
+                        // MSVC)
+#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#endif // __clang__ || __GNUC__ || _MSC_VER
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
+#define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif
+
+#if !defined(JSON_IS_AMALGAMATION)
+
+#include "allocator.h"
+#include "version.h"
+
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+using Int = int;
+using UInt = unsigned int;
+#if defined(JSON_NO_INT64)
+using LargestInt = int;
+using LargestUInt = unsigned int;
+#undef JSON_HAS_INT64
+#else                 // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+using Int64 = __int64;
+using UInt64 = unsigned __int64;
+#else                 // if defined(_MSC_VER) // Other platforms, use long long
+using Int64 = int64_t;
+using UInt64 = uint64_t;
+#endif                // if defined(_MSC_VER)
+using LargestInt = Int64;
+using LargestUInt = UInt64;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+
+template <typename T>
+using Allocator =
+    typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
+                              std::allocator<T>>::type;
+using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
+using IStringStream =
+    std::basic_istringstream<String::value_type, String::traits_type,
+                             String::allocator_type>;
+using OStringStream =
+    std::basic_ostringstream<String::value_type, String::traits_type,
+                             String::allocator_type>;
+using IStream = std::istream;
+using OStream = std::ostream;
+} // namespace Json
+
+// Legacy names (formerly macros).
+using JSONCPP_STRING = Json::String;
+using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
+using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
+using JSONCPP_ISTREAM = Json::IStream;
+using JSONCPP_OSTREAM = Json::OStream;
+
+#endif // JSON_CONFIG_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class StreamWriter;
+class StreamWriterBuilder;
+class Writer;
+class FastWriter;
+class StyledWriter;
+class StyledStreamWriter;
+
+// reader.h
+class Reader;
+class CharReader;
+class CharReaderBuilder;
+
+// json_features.h
+class Features;
+
+// value.h
+using ArrayIndex = unsigned int;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED

File diff suppressed because it is too large
+ 2375 - 0
comx_sdk.node/include/ModelIO.buffer/json/json.h


+ 447 - 0
comx_sdk.node/include/ModelIO.buffer/jsoncpp/json/json-forwards.h

@@ -0,0 +1,447 @@
+/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json-forwards.h"
+/// This header provides forward declaration for all JsonCpp types.
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation,
+tests and demonstration applications, are licensed under the following
+conditions...
+
+Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
+jurisdictions which recognize such a disclaimer. In such jurisdictions,
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
+The JsonCpp Authors, and is released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this
+software may choose to accept it either as 1) Public Domain, 2) under the
+conditions of the MIT License (see below), or 3) under the terms of dual
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
+# define JSON_FORWARD_AMALGAMATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgamated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGAMATION
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+#ifndef JSON_VERSION_H_INCLUDED
+#define JSON_VERSION_H_INCLUDED
+
+// Note: version must be updated in three places when doing a release. This
+// annoying process ensures that amalgamate, CMake, and meson all report the
+// correct version.
+// 1. /meson.build
+// 2. /include/json/version.h
+// 3. /CMakeLists.txt
+// IMPORTANT: also update the SOVERSION!!
+
+#define JSONCPP_VERSION_STRING "1.9.5"
+#define JSONCPP_VERSION_MAJOR 1
+#define JSONCPP_VERSION_MINOR 9
+#define JSONCPP_VERSION_PATCH 5
+#define JSONCPP_VERSION_QUALIFIER
+#define JSONCPP_VERSION_HEXA                                                   \
+  ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) |             \
+   (JSONCPP_VERSION_PATCH << 8))
+
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
+#endif // JSON_VERSION_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_ALLOCATOR_H_INCLUDED
+#define JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+#pragma pack(push)
+#pragma pack()
+
+namespace Json {
+template <typename T> class SecureAllocator {
+public:
+  // Type definitions
+  using value_type = T;
+  using pointer = T*;
+  using const_pointer = const T*;
+  using reference = T&;
+  using const_reference = const T&;
+  using size_type = std::size_t;
+  using difference_type = std::ptrdiff_t;
+
+  /**
+   * Allocate memory for N items using the standard allocator.
+   */
+  pointer allocate(size_type n) {
+    // allocate using "global operator new"
+    return static_cast<pointer>(::operator new(n * sizeof(T)));
+  }
+
+  /**
+   * Release memory which was allocated for N items at pointer P.
+   *
+   * The memory block is filled with zeroes before being released.
+   */
+  void deallocate(pointer p, size_type n) {
+    // memset_s is used because memset may be optimized away by the compiler
+    memset_s(p, n * sizeof(T), 0, n * sizeof(T));
+    // free using "global operator delete"
+    ::operator delete(p);
+  }
+
+  /**
+   * Construct an item in-place at pointer P.
+   */
+  template <typename... Args> void construct(pointer p, Args&&... args) {
+    // construct using "placement new" and "perfect forwarding"
+    ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
+  }
+
+  size_type max_size() const { return size_t(-1) / sizeof(T); }
+
+  pointer address(reference x) const { return std::addressof(x); }
+
+  const_pointer address(const_reference x) const { return std::addressof(x); }
+
+  /**
+   * Destroy an item in-place at pointer P.
+   */
+  void destroy(pointer p) {
+    // destroy using "explicit destructor"
+    p->~T();
+  }
+
+  // Boilerplate
+  SecureAllocator() {}
+  template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
+  template <typename U> struct rebind { using other = SecureAllocator<U>; };
+};
+
+template <typename T, typename U>
+bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+  return true;
+}
+
+template <typename T, typename U>
+bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+  return false;
+}
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#endif // JSON_ALLOCATOR_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+#include <cstddef>
+#include <cstdint>
+#include <istream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+// Temporary, tracked for removal with issue #982.
+#ifndef JSON_USE_NULLREF
+#define JSON_USE_NULLREF 1
+#endif
+
+/// If defined, indicates that the source file is amalgamated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgamated header.
+// #define JSON_IS_AMALGAMATION
+
+// Export macros for DLL visibility
+#if defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#elif defined(__GNUC__) || defined(__clang__)
+#define JSON_API __attribute__((visibility("default")))
+#endif // if defined(_MSC_VER)
+
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_DLL_BUILD
+
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1800
+#error                                                                         \
+    "ERROR:  Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+// As recommended at
+// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
+                                              const char* format, ...);
+#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
+#else
+#define jsoncpp_snprintf std::snprintf
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
+// C++11 should be used directly in JSONCPP.
+#define JSONCPP_OVERRIDE override
+
+#ifdef __clang__
+#if __has_extension(attribute_deprecated_with_message)
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
+#endif
+#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
+#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
+#endif                  // GNUC version
+#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
+                        // MSVC)
+#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#endif // __clang__ || __GNUC__ || _MSC_VER
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
+#define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif
+
+#if !defined(JSON_IS_AMALGAMATION)
+
+#include "allocator.h"
+#include "version.h"
+
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+using Int = int;
+using UInt = unsigned int;
+#if defined(JSON_NO_INT64)
+using LargestInt = int;
+using LargestUInt = unsigned int;
+#undef JSON_HAS_INT64
+#else                 // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+using Int64 = __int64;
+using UInt64 = unsigned __int64;
+#else                 // if defined(_MSC_VER) // Other platforms, use long long
+using Int64 = int64_t;
+using UInt64 = uint64_t;
+#endif                // if defined(_MSC_VER)
+using LargestInt = Int64;
+using LargestUInt = UInt64;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+
+template <typename T>
+using Allocator =
+    typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
+                              std::allocator<T>>::type;
+using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
+using IStringStream =
+    std::basic_istringstream<String::value_type, String::traits_type,
+                             String::allocator_type>;
+using OStringStream =
+    std::basic_ostringstream<String::value_type, String::traits_type,
+                             String::allocator_type>;
+using IStream = std::istream;
+using OStream = std::ostream;
+} // namespace Json
+
+// Legacy names (formerly macros).
+using JSONCPP_STRING = Json::String;
+using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
+using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
+using JSONCPP_ISTREAM = Json::IStream;
+using JSONCPP_OSTREAM = Json::OStream;
+
+#endif // JSON_CONFIG_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class StreamWriter;
+class StreamWriterBuilder;
+class Writer;
+class FastWriter;
+class StyledWriter;
+class StyledStreamWriter;
+
+// reader.h
+class Reader;
+class CharReader;
+class CharReaderBuilder;
+
+// json_features.h
+class Features;
+
+// value.h
+using ArrayIndex = unsigned int;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED

File diff suppressed because it is too large
+ 2375 - 0
comx_sdk.node/include/ModelIO.buffer/jsoncpp/json/json.h


File diff suppressed because it is too large
+ 5342 - 0
comx_sdk.node/include/ModelIO.buffer/jsoncpp/jsoncpp.cpp


BIN
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/TCL.chm


+ 23 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/alpha.h

@@ -0,0 +1,23 @@
+#pragma once
+#include <string>
+
+class Alpha
+{
+public:
+	// constructors/destructor
+	Alpha() : letter(0) {}
+	Alpha(const char _letter ) : letter(_letter) {}
+	~Alpha() {}
+
+	// interface
+	friend bool operator < (const Alpha& lhs, const Alpha& rhs) 
+	{ return lhs.getLetter() < rhs.getLetter(); }
+	friend bool operator == (const Alpha& lhs, const Alpha& rhs)
+	{ return lhs.getLetter() == rhs.getLetter(); }
+	char getLetter() const { return letter; }
+
+private:
+	// data
+	char letter;
+};
+

+ 172 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/associative_tree.h

@@ -0,0 +1,172 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "basic_tree.h"
+#include "child_iterator.h"
+#include "child_node_iterator.h"
+#include "descendant_iterator.h"
+#include "descendant_node_iterator.h"
+#include "reverse_iterator.h"
+#include "reverse_node_iterator.h"
+#include <memory>
+
+namespace tcl 
+{
+	template<typename T, typename U, typename X> class associative_tree;
+
+	// overloaded comparison operations
+	template<typename T, typename U, typename V> bool operator == (const associative_tree<T, U, V>& lhs, const associative_tree<T, U, V>& rhs);
+	template<typename T, typename U, typename V> bool operator <  (const associative_tree<T, U, V>& lhs, const associative_tree<T, U, V>& rhs);
+	template<typename T, typename U, typename V> bool operator != (const associative_tree<T, U, V>& lhs, const associative_tree<T, U, V>& rhs) { return !(lhs == rhs); }
+	template<typename T, typename U, typename V> bool operator >  (const associative_tree<T, U, V>& lhs, const associative_tree<T, U, V>& rhs) { return rhs < lhs; }
+	template<typename T, typename U, typename V> bool operator <= (const associative_tree<T, U, V>& lhs, const associative_tree<T, U, V>& rhs) { return !(rhs < lhs); }
+	template<typename T, typename U, typename V> bool operator >= (const associative_tree<T, U, V>& lhs, const associative_tree<T, U, V>& rhs) { return !(lhs < rhs); }
+}
+
+// stored_type:				type stored in container
+// tree_type:				one of three tree types derived from this base
+// container_type:		type of contain to hold children (can be set or multiset)
+
+template< typename stored_type, typename tree_type,  typename container_type >
+class tcl::associative_tree : public basic_tree<stored_type, tree_type, container_type>
+{
+protected:
+	typedef basic_tree<stored_type, tree_type, container_type> basic_tree_type;
+	explicit associative_tree( const stored_type& stored_obj ) : basic_tree_type(stored_obj) {}
+	virtual ~associative_tree() {}
+
+public:
+	// typedefs
+	typedef associative_tree<stored_type, tree_type, container_type> associative_tree_type;
+	typedef stored_type key_type;
+	using basic_tree_type::size_type;
+
+	// element iterator typedefs
+	typedef const_associative_iterator<stored_type, tree_type, container_type>																				const_iterator;
+	typedef associative_iterator<stored_type, tree_type, container_type>																							iterator;
+	typedef const_pre_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>				const_pre_order_iterator;
+	typedef pre_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>							pre_order_iterator;
+	typedef const_post_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>				const_post_order_iterator;
+	typedef post_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>							post_order_iterator;
+	typedef const_level_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>			const_level_order_iterator;
+	typedef level_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>						level_order_iterator;
+	typedef associative_reverse_iterator<stored_type, tree_type, container_type>																			reverse_iterator;
+	typedef const_associative_reverse_iterator<stored_type, tree_type, container_type>																const_reverse_iterator;
+
+	// node iterator typedefs
+	typedef const_associative_node_iterator<stored_type, tree_type, container_type>																		const_node_iterator;
+	typedef associative_node_iterator<stored_type, tree_type, container_type>																					node_iterator;
+	typedef const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>		const_pre_order_node_iterator;
+	typedef pre_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>					pre_order_node_iterator;
+	typedef const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>	const_post_order_node_iterator;
+	typedef post_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>				post_order_node_iterator;
+	typedef const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type> const_level_order_node_iterator;
+	typedef level_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>				level_order_node_iterator;
+	typedef associative_reverse_node_iterator<stored_type, tree_type, container_type>																	reverse_node_iterator;
+	typedef const_associative_reverse_node_iterator<stored_type, tree_type, container_type>														const_reverse_node_iterator;
+
+	// child element iterator accessors
+	const_iterator begin() const { return const_iterator(basic_tree_type::children.begin(), this); }
+	const_iterator end() const { return const_iterator(basic_tree_type::children.end(), this); }
+	iterator begin() { return iterator(basic_tree_type::children.begin(), this); }
+	iterator end() { return iterator(basic_tree_type::children.end(), this); }
+	
+	// child node iterator accessors
+	const_node_iterator node_begin() const { return const_node_iterator(basic_tree_type::children.begin(), this); }
+	const_node_iterator node_end() const { return const_node_iterator(basic_tree_type::children.end(), this); }
+	node_iterator node_begin() { return node_iterator(basic_tree_type::children.begin(), this); }
+	node_iterator node_end() { return node_iterator(basic_tree_type::children.end(), this); }
+
+	// child element reverse iterator accessors
+	const_reverse_iterator rbegin() const {return const_reverse_iterator(end()); }
+	const_reverse_iterator rend() const {return const_reverse_iterator(begin()); }
+	reverse_iterator rbegin() {return reverse_iterator(end()); }
+	reverse_iterator rend() { return reverse_iterator(begin()); }
+
+	// child node reverse iterator accessors
+	const_reverse_node_iterator node_rbegin() const {return const_reverse_node_iterator(node_end()); }
+	const_reverse_node_iterator node_rend() const {return const_reverse_node_iterator(node_begin()); }
+	reverse_node_iterator node_rbegin() {return reverse_node_iterator(node_end()); }
+	reverse_node_iterator node_rend() { return reverse_node_iterator(node_begin()); }
+
+	// public interface
+	iterator find(const stored_type& value);
+	const_iterator find(const stored_type& value) const;
+	bool erase(const stored_type& value);
+	void erase(iterator it);
+	void erase(iterator it_beg, iterator it_end);
+	void clear();
+	typename basic_tree_type::size_type count(const stored_type& value) const;
+	iterator lower_bound(const stored_type& value);
+	const_iterator lower_bound(const stored_type& value) const;
+	iterator upper_bound(const stored_type& value);
+	const_iterator upper_bound(const stored_type& value) const;
+	std::pair<iterator, iterator> equal_range(const stored_type& value)
+	{
+		tree_type node_obj(value); // create a search node and search local children
+		iterator lower_it(basic_tree_type::children.lower_bound(&node_obj), this);
+		iterator upper_it(basic_tree_type::children.upper_bound(&node_obj), this);
+		return std::make_pair(lower_it, upper_it);
+	}
+	std::pair<const_iterator, const_iterator> equal_range(const stored_type& value) const
+	{
+		tree_type node_obj(value); // create a search node and search local children
+		const_iterator lower_it(basic_tree_type::children.lower_bound(&node_obj), this);
+		const_iterator upper_it(basic_tree_type::children.upper_bound(&node_obj), this);
+		return std::make_pair(lower_it, upper_it);
+	}
+
+protected:
+	iterator insert( const stored_type& value, tree_type* parent ) { return insert(end(), value, parent); }
+	iterator insert(const const_iterator& pos, const stored_type& value, tree_type* parent);
+	iterator insert(const tree_type& tree_obj, tree_type* parent) { return insert(end(), tree_obj, parent); }
+	iterator insert(const const_iterator pos, const tree_type& tree_obj, tree_type* parent);
+	void set(const tree_type& tree_obj, tree_type* parent);
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class const_pre_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>;
+		friend class const_post_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>;
+		friend class const_level_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree_type>;
+		friend class const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>;
+		friend class const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>;
+		friend class const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, associative_tree_type>;
+		friend bool operator == (const associative_tree_type& lhs, const associative_tree_type& rhs);
+		friend bool operator < (const associative_tree_type& lhs, const associative_tree_type& rhs);
+	#else 
+		template<typename T, typename U, typename V, typename W> friend class const_pre_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_post_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_level_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_pre_order_descendant_node_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_post_order_descendant_node_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_level_order_descendant_node_iterator;
+		friend bool operator ==<> (const associative_tree_type& lhs, const associative_tree_type& rhs);
+		friend bool operator < <> (const associative_tree_type& lhs, const associative_tree_type& rhs);
+	#endif
+};
+
+#include "associative_tree.inl"

+ 285 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/associative_tree.inl

@@ -0,0 +1,285 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+
+// find(const stored_type&)
+template< typename stored_type, typename tree_type, typename container_type >
+typename tcl::associative_tree<stored_type, tree_type, container_type>::iterator 
+tcl::associative_tree<stored_type, tree_type, container_type>::find(const stored_type& value) 
+{
+	tree_type node_obj(value); // create a search node and search local children
+	iterator it(basic_tree_type::children.find(&node_obj), this);
+	return it;
+}
+
+// find(const stored_type&) const
+template< typename stored_type, typename tree_type, typename container_type >
+typename tcl::associative_tree<stored_type, tree_type, container_type>::const_iterator 
+tcl::associative_tree<stored_type, tree_type, container_type>::find(const stored_type& value) const
+{
+	tree_type node_obj(value);
+	const_iterator it(basic_tree_type::children.find(&node_obj), this);
+	return it;
+}
+
+
+// erase(const stored_type&)
+template< typename stored_type, typename tree_type, typename container_type >
+bool tcl::associative_tree<stored_type, tree_type, container_type>::
+erase(const stored_type& value)
+{
+	bool erased_nodes = false;
+	tree_type node_obj(value); // create search node
+	typename container_type::iterator it = basic_tree_type::children.find(&node_obj);
+
+	while ( it != basic_tree_type::children.end() ) { // could be multiple nodes (with multitree)
+		deallocate_tree_type(*it); // delete node and remove from children
+		basic_tree_type::children.erase(it);  
+		it = basic_tree_type::children.find(&node_obj);  // any more?
+		erased_nodes = true;
+	}
+	return erased_nodes;
+}
+
+// count(const stored_type&)
+template< typename stored_type, typename tree_type, typename container_type >
+typename tcl::basic_tree<stored_type, tree_type, container_type>::size_type 
+tcl::associative_tree<stored_type, tree_type, container_type>::count(const stored_type& value) const
+{
+	const_iterator it = find(value);
+	const_iterator it_end = end();
+
+	typename basic_tree_type::size_type cnt = 0;
+
+	while (it != it_end && !(*it < value || value < *it)) {
+		++cnt;
+		++it;
+	}
+	return cnt;
+}
+
+// lower_bound(const stored_type&)
+template< typename stored_type, typename tree_type, typename container_type>
+typename tcl::associative_tree<stored_type, tree_type, container_type>::iterator
+tcl::associative_tree<stored_type, tree_type, container_type>::lower_bound(const stored_type& value)
+{
+	tree_type node_obj(value); // create a search node and search local children
+	iterator it(basic_tree_type::children.lower_bound(&node_obj), this);
+	return it;
+}
+
+// lower_bound(const stored_type&) const
+template< typename stored_type, typename tree_type, typename container_type>
+typename tcl::associative_tree<stored_type, tree_type, container_type>::const_iterator
+tcl::associative_tree<stored_type, tree_type, container_type>::lower_bound(const stored_type& value) const
+{
+	tree_type node_obj(value); // create a search node and search local children
+	const_iterator it(basic_tree_type::children.lower_bound(&node_obj), this);
+	return it;
+}
+
+// upper_bound(const stored_type&)
+template< typename stored_type, typename tree_type, typename container_type>
+typename tcl::associative_tree<stored_type, tree_type, container_type>::iterator
+tcl::associative_tree<stored_type, tree_type, container_type>::upper_bound(const stored_type& value)
+{
+	tree_type node_obj(value); // create a search node and search local children
+	iterator it(basic_tree_type::children.upper_bound(&node_obj), this);
+	return it;
+}
+
+// upper_bound(const stored_type&) const
+template< typename stored_type, typename tree_type, typename container_type>
+typename tcl::associative_tree<stored_type, tree_type, container_type>::const_iterator
+tcl::associative_tree<stored_type, tree_type, container_type>::upper_bound(const stored_type& value) const
+{
+	tree_type node_obj(value); // create a search node and search local children
+	const_iterator it(basic_tree_type::children.upper_bound(&node_obj), this);
+	return it;
+}
+
+// insert(iterator, const stored_type&, tree_type*)
+template< typename stored_type, typename tree_type, typename container_type>
+typename tcl::associative_tree<stored_type, tree_type, container_type>::iterator 
+tcl::associative_tree<stored_type, tree_type, container_type>::insert(const const_iterator& pos, const stored_type& value, tree_type* pParent)
+{
+	// create a new tree_type object to hold the node object
+	tree_type* pNew_node; 
+	basic_tree_type::allocate_tree_type(pNew_node, tree_type(value));
+	pNew_node->set_parent(pParent);
+
+	const typename basic_tree_type::size_type sz = basic_tree_type::children.size();
+
+	typename container_type::iterator children_pos;
+	if ( pos == pParent->end()) {
+		children_pos = basic_tree_type::children.end();
+	} else {
+		// get non-const iterator position from pos
+		children_pos = basic_tree_type::children.begin();
+		typename container_type::const_iterator const_children_pos = basic_tree_type::children.begin();
+		while ( const_children_pos != pos.it && const_children_pos != basic_tree_type::children.end()) {
+			++children_pos;
+			++const_children_pos;
+		}
+	}
+
+	// insert the tree node into the children container
+	const typename container_type::iterator it = basic_tree_type::children.insert(children_pos, pNew_node);
+
+	if ( sz == basic_tree_type::children.size() ) { // check for successful insertion
+		basic_tree_type::deallocate_tree_type(pNew_node);  // not successful.  delete new node and return end()
+		return iterator(basic_tree_type::children.end(), this);
+	}
+
+	return iterator(it, this);
+}
+
+// insert(iterator, const tree_type&, tree_type*)
+template< typename stored_type, typename tree_type, typename container_type>
+typename tcl::associative_tree<stored_type, tree_type, container_type>::iterator 
+tcl::associative_tree<stored_type, tree_type, container_type>::insert(const const_iterator pos, const tree_type& tree_obj, tree_type* pParent)
+{
+	// insert current node
+	iterator base_it = pParent->insert(pos, *tree_obj.get());
+
+	if ( base_it != pParent->end() ) {
+		const_iterator it = tree_obj.begin();
+		const const_iterator it_end = tree_obj.end();
+
+		// call this function recursively thru derived tree for children
+		for ( ; it != it_end; ++it )
+			base_it.node()->insert(*it.node());
+	}
+	return base_it;
+}
+
+// set(const tree_type&, tree_type*)
+template< typename stored_type, typename tree_type, typename container_type>
+void tcl::associative_tree<stored_type, tree_type, container_type>::set(const tree_type& tree_obj, tree_type* pParent)
+{
+	set(*tree_obj.get()); // set data for this node
+
+	const_iterator it = tree_obj.begin();
+	const const_iterator it_end = tree_obj.end();
+	for ( ; it != it_end; ++it ) { // and insert all descendants of passed tree
+		insert(*it.node(), pParent );
+	}
+}
+
+// clear()
+template< typename stored_type, typename tree_type, typename container_type>
+void tcl::associative_tree<stored_type, tree_type, container_type>::clear()
+{
+	iterator it = begin();
+	const iterator it_end = end();
+	for ( ; it != it_end; ++it )
+	{
+		basic_tree_type::deallocate_tree_type(it.node()); // delete all child nodes
+	}
+	basic_tree_type::children.clear();  // and remove them from set
+}
+
+// erase(iterator)
+template< typename stored_type, typename tree_type, typename container_type>
+void tcl::associative_tree<stored_type, tree_type, container_type>::erase(iterator it) 
+{ 
+	// check for node presence
+	if (it.pParent != this)
+		return;
+
+	// clear children
+	it.node()->clear(); 
+	deallocate_tree_type(it.node());
+
+	const iterator beg_it = begin();
+	typename container_type::iterator pos_it = basic_tree_type::children.begin();
+	for ( ; it != beg_it; --it, ++pos_it) ;  // get child iterator position
+
+	basic_tree_type::children.erase(pos_it);
+}
+
+// erase(iterator, iterator)
+template< typename stored_type, typename tree_type, typename container_type>
+void tcl::associative_tree<stored_type, tree_type, container_type>::erase(iterator it_beg, iterator it_end)
+{
+	while (it_beg != it_end) {
+		erase(it_beg++);
+	}
+}
+
+
+// operator ==
+template<typename stored_type, typename tree_type, typename container_type>
+bool tcl::operator == (const associative_tree<stored_type, tree_type, container_type>& lhs, const associative_tree<stored_type, tree_type, container_type>& rhs)
+{
+	// check this node
+	if ((*lhs.get() < *rhs.get()) || (*rhs.get() < *lhs.get()))
+		return false;
+
+	typename associative_tree<stored_type, tree_type, container_type>::const_iterator lhs_it = lhs.begin();
+	const typename associative_tree<stored_type, tree_type, container_type>::const_iterator lhs_end = lhs.end();
+	typename associative_tree<stored_type, tree_type, container_type>::const_iterator rhs_it = rhs.begin();
+	const typename associative_tree<stored_type, tree_type, container_type>::const_iterator rhs_end = rhs.end();
+
+	for ( ; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it ) {
+		if (*lhs_it.node() != *rhs_it.node()) {
+			return false;
+		}
+	}
+
+	if (lhs_it != lhs.end() || rhs_it != rhs.end())
+		return false;
+
+	return true;
+}
+
+
+// operator <
+template<typename stored_type, typename tree_type, typename container_type>
+bool tcl::operator < (const associative_tree<stored_type, tree_type, container_type>& lhs, const associative_tree<stored_type, tree_type, container_type>& rhs) 
+{
+	// check this node
+	if (*lhs.get() < *rhs.get())
+		return true;
+
+	typename associative_tree<stored_type, tree_type, container_type>::const_iterator lhs_it = lhs.begin();
+	const typename associative_tree<stored_type, tree_type, container_type>::const_iterator lhs_end = lhs.end();
+	typename associative_tree<stored_type, tree_type, container_type>::const_iterator rhs_it = rhs.begin();
+	const typename associative_tree<stored_type, tree_type, container_type>::const_iterator rhs_end = rhs.end();
+
+	for ( ; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it ) {
+		if (*lhs_it.node() < *rhs_it.node()) {
+			return true;
+		}
+	}
+
+	if (lhs.size() != rhs.size()) {
+		return lhs.size() < rhs.size();
+	}
+
+	return false;
+}
+

+ 101 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/basic_tree.h

@@ -0,0 +1,101 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+	you must not claim that you wrote the original software. 
+	If you use this software in a product, an acknowledgment in the product 
+	documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+	and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+	or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include <set>
+#include <stack>
+#include <queue>
+#include <algorithm>
+#include <limits>
+
+namespace tcl 
+{
+	template<typename T, typename U, typename V> class basic_tree;
+}
+
+// stored_type:			type stored in container
+// tree_type:			one of three tree types derived from this base
+// container_type:		type of contain to hold children (can be set or multiset)
+
+template< typename stored_type, typename tree_type,  typename container_type >
+class tcl::basic_tree 
+{
+	public:
+	// typedefs
+		typedef basic_tree<stored_type, tree_type, container_type> basic_tree_type;
+		typedef stored_type* (*tClone_fcn) (const stored_type&);
+		typedef stored_type value_type;
+		typedef stored_type& reference;
+		typedef const stored_type& const_reference;
+		typedef size_t size_type;
+		typedef std::allocator<stored_type> allocator_type;
+		typedef typename allocator_type::difference_type difference_type;
+
+	protected:
+	// constructors/destructor
+		basic_tree() : pElement(0), pParent_node(0)  {}
+		explicit basic_tree(const stored_type& value);
+		basic_tree(const basic_tree_type& rhs);  // copy constructor
+		virtual ~basic_tree();
+
+	public:
+	// public interface
+		const stored_type* get() const { return pElement; }
+		stored_type* get() { return pElement; }
+		bool is_root() const { return pParent_node == 0; }
+		size_type size() const { return children.size(); }
+		size_type max_size() const { return (std::numeric_limits<int>().max)(); }
+		bool empty() const { return children.empty(); }
+		tree_type* parent() { return pParent_node; }
+		const tree_type* parent() const { return pParent_node; }
+		static void set_clone(const tClone_fcn& fcn) { pClone_fcn = fcn; }
+
+
+	protected:
+		void set_parent(tree_type* pParent) { pParent_node = pParent; }
+		basic_tree_type& operator = (const basic_tree_type& rhs); // assignment operator
+		void set(const stored_type& stored_obj);
+		void allocate_stored_type(stored_type*& element_ptr, const stored_type& value) 
+			{ element_ptr = stored_type_allocator.allocate(1,0); stored_type_allocator.construct(element_ptr, value); }
+		void deallocate_stored_type(stored_type* element_ptr) 
+			{ stored_type_allocator.destroy(element_ptr); stored_type_allocator.deallocate(element_ptr, 1); }
+		void allocate_tree_type(tree_type*& tree_ptr, const tree_type& tree_obj)
+			{ tree_ptr = tree_type_allocator.allocate(1,0); tree_type_allocator.construct(tree_ptr, tree_obj); }
+		void deallocate_tree_type(tree_type* tree_ptr)
+			{ tree_type_allocator.destroy(tree_ptr); tree_type_allocator.deallocate(tree_ptr, 1); }
+		
+	// data
+	protected:
+		container_type children;
+	private:
+		stored_type* pElement;   // data accessor
+		mutable tree_type* pParent_node;
+		static tClone_fcn pClone_fcn;
+		std::allocator<stored_type> stored_type_allocator;
+		std::allocator<tree_type> tree_type_allocator;
+};
+
+#include "basic_tree.inl"

+ 93 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/basic_tree.inl

@@ -0,0 +1,93 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+
+// static member variable definition
+template< typename stored_type, typename tree_type, typename container_type >
+typename tcl::basic_tree<stored_type, tree_type, container_type>::tClone_fcn
+tcl::basic_tree<stored_type, tree_type, container_type>::pClone_fcn = 0;
+
+// constructor
+template< typename stored_type, typename tree_type, typename container_type >
+tcl::basic_tree<stored_type, tree_type, container_type>::basic_tree(const stored_type& value) 
+:	children(container_type()), pElement(0), pParent_node(0), 
+	stored_type_allocator(std::allocator<stored_type>()), tree_type_allocator(std::allocator<tree_type>())
+{
+	// use clone function if available
+	if ( pClone_fcn )
+		pElement = pClone_fcn(value);
+	else
+		allocate_stored_type(pElement, value);
+}
+
+
+// copy constructor
+template< typename stored_type, typename tree_type, typename container_type >
+tcl::basic_tree<stored_type, tree_type, container_type>::basic_tree(const basic_tree_type& rhs) 
+:	children(container_type()), pElement(0), pParent_node(0), 
+	stored_type_allocator(std::allocator<stored_type>()), tree_type_allocator(std::allocator<tree_type>())
+{
+	pParent_node = 0; // new tree obj is always root node
+	set(*rhs.get()); // set data obj
+}
+
+// assignment operator
+template< typename stored_type, typename tree_type, typename container_type >
+tcl::basic_tree<stored_type, tree_type, container_type>& tcl::basic_tree<stored_type, tree_type, container_type>::operator = (const basic_tree_type& rhs)
+{
+	if ( &rhs == this )
+		return *this;
+
+	set(*rhs.get());  // set data obj
+
+	return *this;
+}
+
+// destructor
+template< typename stored_type, typename tree_type, typename container_type >
+tcl::basic_tree<stored_type, tree_type, container_type>::~basic_tree()
+{
+	deallocate_stored_type(pElement);
+}
+
+
+
+// set(stored_type&)
+template< typename stored_type, typename tree_type, typename container_type >
+void  tcl::basic_tree<stored_type, tree_type, container_type>::set(const stored_type& value) 
+{ 
+	if ( pElement ) // if data node already exists, free memory
+		deallocate_stored_type(pElement); 
+
+	if ( pClone_fcn )  // use clone fcn if available
+		pElement = pClone_fcn(value);
+	else
+		allocate_stored_type(pElement, value);
+}
+
+
+
+

+ 246 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/child_iterator.h

@@ -0,0 +1,246 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include <set>
+#include <stack>
+#include <queue>
+#include <algorithm>
+#include <iterator>
+
+namespace tcl 
+{
+	// forward declaration
+	template<typename T, typename U, typename V> class basic_tree;
+	template<typename T> class sequential_tree;
+	template<typename T, typename U, typename V> class associative_tree;
+	template<typename T, typename U, typename V> class associative_reverse_iterator;
+	template<typename T, typename U, typename V> class sequential_reverse_iterator;
+	template<typename T, typename U, typename V, typename W> class const_pre_order_descendant_iterator;
+	template<typename T, typename U, typename V, typename W> class const_post_order_descendant_iterator;
+
+	template<typename T, typename U, typename V> class const_associative_iterator;
+	template<typename T, typename U, typename V> class associative_iterator;
+	template<typename T, typename U, typename V> class const_sequential_iterator;
+	template<typename T, typename U, typename V> class sequential_iterator;
+
+	// comparison operators
+	template<typename T, typename U, typename V> bool operator == (const const_associative_iterator<T, U, V>& lhs, const const_associative_iterator<T, U, V>& rhs) { return lhs.pParent == rhs.pParent && lhs.it == rhs.it; }
+	template<typename T, typename U, typename V> bool operator != (const const_associative_iterator<T, U, V>& lhs, const const_associative_iterator<T, U, V>& rhs) { return !(lhs == rhs); }
+
+	template<typename T, typename U, typename V> bool operator == (const const_sequential_iterator<T, U, V>& lhs, const const_sequential_iterator<T, U, V>& rhs ) { return lhs.pParent == rhs.pParent && lhs.it == rhs.it; }
+	template<typename T, typename U, typename V> bool operator != (const const_sequential_iterator<T, U, V>& lhs, const const_sequential_iterator<T, U, V>& rhs ) { return !(lhs == rhs); }
+	template<typename T, typename U, typename V> bool operator < (const const_sequential_iterator<T, U, V>& lhs, const const_sequential_iterator<T, U, V>& rhs) { return lhs.it < rhs.it && lhs.pParent == rhs.pParent; }
+	template<typename T, typename U, typename V> bool operator <= (const const_sequential_iterator<T, U, V>& lhs, const const_sequential_iterator<T, U, V>& rhs) { return lhs < rhs || lhs == rhs; }
+	template<typename T, typename U, typename V> bool operator > (const const_sequential_iterator<T, U, V>& lhs, const const_sequential_iterator<T, U, V>& rhs) { return !(lhs <= rhs); }
+	template<typename T, typename U, typename V> bool operator >= (const const_sequential_iterator<T, U, V>& lhs, const const_sequential_iterator<T, U, V>& rhs) { return !(lhs < rhs); }
+
+}
+
+
+/************************************************************************/
+/* associative tree child iterators                                     */
+/************************************************************************/
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_associative_iterator : public std::iterator<std::bidirectional_iterator_tag, stored_type>
+{
+public:
+	// constructors/destructor
+	const_associative_iterator() : pParent(0) {}
+	virtual ~const_associative_iterator() {}
+protected:
+	explicit const_associative_iterator(typename container_type::const_iterator iter, const associative_tree<stored_type, tree_type, container_type>* pCalled_node) : it(iter), pParent(pCalled_node) {}
+	// copy constructor, and assignment operator will be compiler generated correctly
+
+public:
+	// overloaded operators
+	const stored_type& operator*() const { return  *(*it)->get(); }
+	const stored_type* operator->() const { return (*it)->get(); }
+
+	const_associative_iterator& operator ++() { ++it; return *this; }
+	const_associative_iterator operator ++(int) { const_associative_iterator old(*this); ++*this; return old; }
+	const_associative_iterator& operator --() { --it; return *this; }
+	const_associative_iterator operator --(int) { const_associative_iterator old(*this); --*this; return old; }
+
+	// public interface
+	const tree_type* node() const { return *it; }
+
+	// data
+protected:
+	typename container_type::const_iterator it;
+	const associative_tree<stored_type, tree_type, container_type>* pParent;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class basic_tree<stored_type, tree_type, container_type>;
+		friend class associative_tree<stored_type, tree_type, container_type>;
+		friend class const_pre_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree<stored_type, tree_type, container_type> >;
+		friend class const_post_order_descendant_iterator<stored_type, tree_type, container_type, associative_tree<stored_type, tree_type, container_type> >;
+		friend bool operator == (const const_associative_iterator& lhs, const const_associative_iterator& rhs);
+	#else
+		template<typename T, typename U, typename V> friend class basic_tree;
+		template<typename T, typename U, typename V> friend class associative_tree;
+		template<typename T, typename U, typename V, typename W> friend class const_pre_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_post_order_descendant_iterator;
+		friend bool operator ==<> (const const_associative_iterator& lhs, const const_associative_iterator& rhs);
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::associative_iterator : public tcl::const_associative_iterator<stored_type, tree_type, container_type>
+{
+private:
+public:
+	// constructors/destructor
+	associative_iterator() : const_associative_iterator<stored_type, tree_type, container_type>() {}
+private:
+	explicit associative_iterator(typename container_type::iterator iter, associative_tree<stored_type, tree_type, container_type>* pCalled_node) : const_associative_iterator<stored_type, tree_type, container_type>(iter, pCalled_node) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+
+public:
+	// overloaded operators
+	stored_type& operator*() const { return *(*it)->get(); }
+	stored_type* operator->() const { return (*it)->get(); }
+	associative_iterator& operator ++() { ++it;  return *this; }
+	associative_iterator operator ++(int) { associative_iterator old(*this); ++*this; return old; }
+	associative_iterator& operator --() { --it; return *this; }
+	associative_iterator operator --(int) { associative_iterator old(*this); --*this; return old; }
+
+	tree_type* node() const { return *it; }
+
+	// friends
+	using const_associative_iterator<stored_type, tree_type, container_type>::it;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class associative_tree<stored_type, tree_type, container_type>;
+		friend class associative_reverse_iterator<stored_type, tree_type, container_type>;
+	#else
+		template<typename T, typename U, typename V> friend class associative_tree;
+		template<typename T, typename U, typename V> friend class associative_reverse_iterator;
+	#endif
+};
+
+/************************************************************************/
+/* sequential tree child iterators                                      */
+/************************************************************************/
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_sequential_iterator : public std::iterator<std::random_access_iterator_tag, stored_type>
+{
+public:
+	// constructors/destructor
+	const_sequential_iterator() : pParent(0) {}
+	virtual ~const_sequential_iterator() {}
+protected:
+	explicit const_sequential_iterator(typename container_type::const_iterator iter, const tree_type* pCalled_node) : it(iter), pParent(pCalled_node) {}
+	// copy constructor, and assignment operator will be compiler generated correctly
+
+public:
+	// typedefs
+	typedef size_t size_type;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef std::iterator_traits<std::iterator<std::random_access_iterator_tag, stored_type> >::distance_type difference_type;
+	#else
+		typedef typename std::iterator_traits<const_sequential_iterator>::difference_type difference_type;
+	#endif
+
+	// overloaded operators
+	const stored_type& operator*() const { return  *(*it)->get(); }
+	const stored_type* operator->() const { return (*it)->get(); }
+
+	const_sequential_iterator& operator ++() { ++it; return *this; }
+	const_sequential_iterator operator ++(int) { const_sequential_iterator old(*this); ++*this; return old; }
+	const_sequential_iterator& operator --() { --it; return *this; }
+	const_sequential_iterator operator --(int) { const_sequential_iterator old(*this); --*this; return old; }
+	const_sequential_iterator& operator +=(difference_type n) { it += n; return *this; }
+	const_sequential_iterator& operator -=(difference_type n) { it -= n; return *this; }
+	difference_type operator -(const const_sequential_iterator& rhs) const { return it - rhs.it; }
+	const tree_type* node() const { return *it; }
+
+	// data
+protected:
+	typename container_type::const_iterator it;
+	const tree_type* pParent;
+
+	// friends 
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class sequential_tree<stored_type>;
+		friend class const_pre_order_descendant_iterator<stored_type, tree_type, container_type, sequential_tree<stored_type> >;
+		friend class const_post_order_descendant_iterator<stored_type, tree_type, container_type, sequential_tree<stored_type> >;
+		friend bool operator == (const const_sequential_iterator& lhs, const const_sequential_iterator& rhs );
+		friend bool operator <  (const const_sequential_iterator& lhs, const const_sequential_iterator& rhs);
+	#else
+		friend bool operator ==<> (const const_sequential_iterator& lhs, const const_sequential_iterator& rhs );
+		friend bool operator < <> (const const_sequential_iterator& lhs, const const_sequential_iterator& rhs);
+		template<typename T> friend class sequential_tree;
+		template<typename T, typename U, typename V, typename W> friend class const_pre_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_post_order_descendant_iterator;
+	#endif
+};
+
+
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::sequential_iterator : public tcl::const_sequential_iterator<stored_type, tree_type, container_type>
+{
+public:
+	// constructors/destructor
+	sequential_iterator() : const_sequential_iterator<stored_type, tree_type, container_type>() {}
+private:
+	explicit sequential_iterator(const typename container_type::iterator& iter, const tree_type* const pCalled_node) : const_sequential_iterator<stored_type, tree_type, container_type>(iter, pCalled_node) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+
+public:
+	// overloaded operators
+	stored_type& operator*() const { return *(*it)->get(); }
+	stored_type* operator->() const { return (*it)->get(); }
+	sequential_iterator& operator ++() { ++it;  return *this; }
+	sequential_iterator operator ++(int) { sequential_iterator old(*this); ++*this; return old; }
+	sequential_iterator& operator --() { --it; return *this; }
+	sequential_iterator operator --(int) { sequential_iterator old(*this); --*this; return old; }
+	tree_type* node() const { return *it; }
+
+	// friends
+	using const_sequential_iterator<stored_type, tree_type, container_type>::it;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class sequential_tree<stored_type>;
+		friend class sequential_reverse_iterator<stored_type, tree_type, container_type>;
+	#else
+		template<typename T> friend class sequential_tree;
+		template<typename T, typename U, typename V> friend class sequential_reverse_iterator;
+	#endif
+};
+
+
+
+
+
+
+
+

+ 225 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/child_node_iterator.h

@@ -0,0 +1,225 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include <set>
+#include <stack>
+#include <queue>
+#include <algorithm>
+#include <iterator>
+
+namespace tcl 
+{
+	// forward declaration
+	template<typename stored_type, typename tree_type, typename container_type> class basic_tree;
+	template<typename stored_type> class sequential_tree;
+	template<typename stored_type, typename tree_type, typename container_type> class associative_tree;
+	template<typename stored_type, typename tree_type, typename container_type> class associative_reverse_iterator;
+	template<typename stored_type, typename tree_type, typename container_type> class sequential_reverse_iterator;
+	template<typename stored_type, typename tree_type, typename container_type> class associative_reverse_node_iterator;
+	template<typename stored_type, typename tree_type, typename container_type> class sequential_reverse_node_iterator;
+
+	template<typename T, typename U, typename V> class const_associative_node_iterator;
+	template<typename T, typename U, typename V> class associative_node_iterator;
+	template<typename T, typename U, typename V> class const_sequential_node_iterator;
+	template<typename T, typename U, typename V> class sequential_node_iterator;
+
+	// comparison operators
+	template<typename T, typename U, typename V> bool operator == (const const_associative_node_iterator<T, U, V>& lhs, const const_associative_node_iterator<T, U, V>& rhs ) { return lhs.pParent == rhs.pParent && lhs.it == rhs.it; }
+	template<typename T, typename U, typename V> bool operator != (const const_associative_node_iterator<T, U, V>& lhs, const const_associative_node_iterator<T, U, V>& rhs ) { return !(lhs == rhs); }
+
+	template<typename T, typename U, typename V> bool operator == (const const_sequential_node_iterator<T, U, V>& lhs, const const_sequential_node_iterator<T, U, V>& rhs) { return lhs.pParent == rhs.pParent && lhs.it == rhs.it; }
+	template<typename T, typename U, typename V> bool operator != (const const_sequential_node_iterator<T, U, V>& lhs, const const_sequential_node_iterator<T, U, V>& rhs) { return !(lhs == rhs); }
+	template<typename T, typename U, typename V> bool operator < (const const_sequential_node_iterator<T, U, V>& lhs, const const_sequential_node_iterator<T, U, V>& rhs) { return lhs.it < rhs.it && lhs.pParent == rhs.pParent; }
+	template<typename T, typename U, typename V> bool operator <= (const const_sequential_node_iterator<T, U, V>& lhs, const const_sequential_node_iterator<T, U, V>& rhs) { return lhs <= rhs || lhs == rhs; }
+	template<typename T, typename U, typename V> bool operator > (const const_sequential_node_iterator<T, U, V>& lhs, const const_sequential_node_iterator<T, U, V>& rhs) { return !(lhs <= rhs); }
+	template<typename T, typename U, typename V> bool operator >= (const const_sequential_node_iterator<T, U, V>& lhs, const const_sequential_node_iterator<T, U, V>& rhs) { return !(lhs < rhs); }
+}
+
+
+/************************************************************************/
+/* associative tree child node iterators                                */
+/************************************************************************/
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_associative_node_iterator : public std::iterator<std::bidirectional_iterator_tag, tree_type>
+{
+private:
+public:
+	// constructors/destructor
+	const_associative_node_iterator() : pParent(0) {}
+	explicit const_associative_node_iterator(typename container_type::const_iterator iter, const associative_tree<stored_type, tree_type, container_type>* pCalled_node) : it(iter), pParent(pCalled_node) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+
+	// overloaded operators
+	const tree_type& operator*() const { return  *(*it); }
+	const tree_type* operator->() const { return *it; }
+
+	const_associative_node_iterator& operator ++() { ++it; return *this; }
+	const_associative_node_iterator operator ++(int) { const_associative_node_iterator old(*this); ++*this; return old; }
+	const_associative_node_iterator& operator --() { --it; return *this; }
+	const_associative_node_iterator operator --(int) { const_associative_node_iterator old(*this); --*this; return old; }
+
+	// data
+protected:
+	typename container_type::const_iterator it;
+	const associative_tree<stored_type, tree_type, container_type>* pParent;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class basic_tree<stored_type, tree_type, container_type>;
+		friend class associative_tree<stored_type, tree_type, container_type>;
+		friend bool operator == (const const_associative_node_iterator& lhs, const const_associative_node_iterator& rhs );
+	#else
+		template<typename T, typename U, typename V> friend class basic_tree;
+		template<typename T, typename U, typename V> friend class associative_tree;
+		friend bool operator ==<> (const const_associative_node_iterator& lhs, const const_associative_node_iterator& rhs );
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::associative_node_iterator : public tcl::const_associative_node_iterator<stored_type, tree_type, container_type>
+{
+public:
+	// constructors/destructor
+	associative_node_iterator() : const_associative_node_iterator<stored_type, tree_type, container_type>() {}
+	explicit associative_node_iterator(typename container_type::iterator iter, associative_tree<stored_type, tree_type, container_type>* pCalled_node) : const_associative_node_iterator<stored_type, tree_type, container_type>(iter, pCalled_node) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+
+	// overloaded operators
+	tree_type& operator*() const { return *(*it); }
+	tree_type* operator->() const { return *it; }
+	associative_node_iterator& operator ++() { ++it;  return *this; }
+	associative_node_iterator operator ++(int) { associative_node_iterator old(*this); ++*this; return old; }
+	associative_node_iterator& operator --() { --it; return *this; }
+	associative_node_iterator operator --(int) { associative_node_iterator old(*this); --*this; return old; }
+
+	// friends
+	using const_associative_node_iterator<stored_type, tree_type, container_type>::it;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class associative_tree<stored_type, tree_type, container_type>;
+		friend class associative_reverse_node_iterator<stored_type, tree_type, container_type>;
+	#else
+		template<typename T, typename U, typename V> friend class associative_tree;
+		template<typename T, typename U, typename V> friend class associative_reverse_node_iterator;
+	#endif
+};
+
+/************************************************************************/
+/* sequential tree child iterators                                      */
+/************************************************************************/
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_sequential_node_iterator : public std::iterator<std::random_access_iterator_tag, tree_type>
+{
+public:
+
+	// constructors/destructor
+	const_sequential_node_iterator() : pParent(0) {}
+	explicit const_sequential_node_iterator(typename container_type::const_iterator it_, const tree_type* pParent_) : it(it_), pParent(pParent_) {}
+	virtual ~const_sequential_node_iterator() {}
+	// copy constructor, and assignment operator will be compiler generated correctly
+
+	// typedefs
+	typedef size_t size_type;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef std::iterator_traits<std::iterator<std::random_access_iterator_tag, tree_type> >::distance_type difference_type;
+	#else
+		typedef typename std::iterator_traits<const_sequential_node_iterator>::difference_type difference_type;
+	#endif
+
+	// overloaded operators
+	const tree_type& operator*() const { return  *(*it); }
+	const tree_type* operator->() const { return *it; }
+
+	const_sequential_node_iterator& operator ++() { ++it; return *this; }
+	const_sequential_node_iterator operator ++(int) { const_sequential_node_iterator old(*this); ++*this; return old; }
+	const_sequential_node_iterator& operator --() { --it; return *this; }
+	const_sequential_node_iterator operator --(int) { const_sequential_node_iterator old(*this); --*this; return old; }
+	const_sequential_node_iterator& operator +=(size_type n) { it += n; return *this; }
+	const_sequential_node_iterator& operator -=(size_type n) { it -= n; return *this; }
+	difference_type operator -(const const_sequential_node_iterator& rhs) const { return it - rhs.it; }
+
+	// data
+protected:
+	typename container_type::const_iterator it;
+	const tree_type* pParent;
+
+	// friends 
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class sequential_tree<stored_type>;
+		friend bool operator == (const const_sequential_node_iterator& lhs, const const_sequential_node_iterator& rhs);
+		friend bool operator < (const const_sequential_node_iterator& lhs, const const_sequential_node_iterator& rhs);
+	#else
+		template<typename T> friend class sequential_tree;
+		friend bool operator ==<> (const const_sequential_node_iterator& lhs, const const_sequential_node_iterator& rhs);
+		friend bool operator < <> (const const_sequential_node_iterator& lhs, const const_sequential_node_iterator& rhs);
+	#endif
+};
+
+
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::sequential_node_iterator : public tcl::const_sequential_node_iterator<stored_type, tree_type, container_type>
+{
+private:
+public:
+	// constructors/destructor
+	sequential_node_iterator() : const_sequential_node_iterator<stored_type, tree_type, container_type>() {}
+	explicit sequential_node_iterator(typename container_type::iterator it_, tree_type* pParent_) : const_sequential_node_iterator<stored_type, tree_type, container_type>(it_, pParent_) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+
+	// overloaded operators
+	tree_type& operator*() const { return *(*it); }
+	tree_type* operator->() const { return *it; }
+	sequential_node_iterator& operator ++() { ++it;  return *this; }
+	sequential_node_iterator operator ++(int) { sequential_node_iterator old(*this); ++*this; return old; }
+	sequential_node_iterator& operator --() { --it; return *this; }
+	sequential_node_iterator operator --(int) { sequential_node_iterator old(*this); --*this; return old; }
+
+	// public interface
+	tree_type* node() const { return *it; }
+
+	// friends
+	using const_sequential_node_iterator<stored_type, tree_type, container_type>::it;
+#if defined(_MSC_VER) && _MSC_VER < 1300
+	friend class sequential_tree<stored_type>;
+	friend class sequential_reverse_node_iterator<stored_type, tree_type, container_type>;
+#else
+	template<typename T> friend class sequential_tree;
+	template<typename T, typename U, typename V> friend class sequential_reverse_node_iterator;
+#endif
+};
+
+
+
+
+
+
+
+

+ 308 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_iterator.h

@@ -0,0 +1,308 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "child_iterator.h"
+#include <set>
+#include <stack>
+#include <queue>
+#include <algorithm>
+
+namespace tcl 
+{
+	template<typename T, typename U, typename V, typename W> class const_pre_order_descendant_iterator;
+	template<typename T, typename U, typename V, typename W> class pre_order_descendant_iterator;
+	template<typename T, typename U, typename V, typename W> class const_post_order_descendant_iterator;
+	template<typename T, typename U, typename V, typename W> class post_order_descendant_iterator;
+	template<typename T, typename U, typename V, typename W> class const_level_order_descendant_iterator;
+	template<typename T, typename U, typename V, typename W> class level_order_descendant_iterator;
+	template<typename T, typename U> class tree;
+	template<typename T, typename U> class multitree;
+	template<typename T, typename U, typename V> class unique_tree;
+
+	// comparison operators
+	template<typename T, typename U, typename V, typename W> bool operator == (const const_pre_order_descendant_iterator<T, U, V, W>& lhs, const const_pre_order_descendant_iterator<T, U, V, W>& rhs ) { return lhs.it == rhs.it && lhs.at_top == rhs.at_top; }
+	template<typename T, typename U, typename V, typename W> bool operator != (const const_pre_order_descendant_iterator<T, U, V, W>& lhs, const const_pre_order_descendant_iterator<T, U, V, W>& rhs ) { return !(lhs == rhs); }
+	template<typename T, typename U, typename V, typename W> bool operator == ( const const_post_order_descendant_iterator<T, U, V, W>& lhs, const const_post_order_descendant_iterator<T, U, V, W>& rhs ) { return lhs.it == rhs.it && lhs.at_top == rhs.at_top; }
+	template<typename T, typename U, typename V, typename W> bool operator != ( const const_post_order_descendant_iterator<T, U, V, W>& lhs, const const_post_order_descendant_iterator<T, U, V, W>& rhs ) { return !(lhs == rhs); }
+	template<typename T, typename U, typename V, typename W> bool operator == (const const_level_order_descendant_iterator<T, U, V, W>& lhs, const const_level_order_descendant_iterator<T, U, V, W>& rhs) { return lhs.it == rhs.it && lhs.at_top == rhs.at_top; }
+	template<typename T, typename U, typename V, typename W> bool operator != (const const_level_order_descendant_iterator<T, U, V, W>& lhs, const const_level_order_descendant_iterator<T, U, V, W>& rhs) { return !(lhs == rhs); }
+}
+
+
+/************************************************************************/
+/* descendant iterators                                                 */
+/************************************************************************/
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::const_pre_order_descendant_iterator : public std::iterator<std::bidirectional_iterator_tag, stored_type>
+{
+public:
+	// constructors/destructor
+	const_pre_order_descendant_iterator() : pTop_node(0), at_top(false) {}
+	virtual ~const_pre_order_descendant_iterator() {}
+	//  copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit const_pre_order_descendant_iterator(const tree_type* pCalled_node, bool beg) : it(beg ? pCalled_node->begin() : pCalled_node->end()), pTop_node(pCalled_node), at_top(beg) {}
+
+public:
+	// overloaded operators
+	const_pre_order_descendant_iterator& operator ++(); 
+	const_pre_order_descendant_iterator operator ++(int) { const_pre_order_descendant_iterator old(*this); ++*this; return old; }
+	const_pre_order_descendant_iterator& operator --();
+	const_pre_order_descendant_iterator operator --(int) { const_pre_order_descendant_iterator old(*this); --*this; return old; }
+
+	// public interface
+	const stored_type& operator*() const { return  at_top ? *pTop_node->get() : it.operator *(); }
+	const stored_type* operator->() const { return at_top ? pTop_node->get() : it.operator ->(); }
+	const tree_type* node() const { return at_top ? pTop_node : it.node(); }
+
+	// data
+protected:
+	typename tree_category_type::const_iterator it;
+	std::stack<typename tree_category_type::const_iterator> node_stack;   
+	const tree_type* pTop_node;
+	typename container_type::const_reverse_iterator rit;
+	bool at_top;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+    typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+		friend bool operator == (const const_pre_order_descendant_iterator& lhs, const const_pre_order_descendant_iterator& rhs );
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+		friend bool operator ==<> (const const_pre_order_descendant_iterator& lhs, const const_pre_order_descendant_iterator& rhs );
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::pre_order_descendant_iterator : public tcl::const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>
+{
+public:
+	// constructors/destructor
+	pre_order_descendant_iterator() : const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>() {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit pre_order_descendant_iterator(const tree_type* const pCalled_node, bool beg) : const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>(pCalled_node, beg) {}
+
+public:
+	// overloaded operators
+	pre_order_descendant_iterator& operator ++() { ++(*static_cast<const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	pre_order_descendant_iterator operator ++(int) { pre_order_descendant_iterator old(*this); ++*this; return old; }
+	pre_order_descendant_iterator& operator --() { --(*static_cast<const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	pre_order_descendant_iterator operator --(int) { pre_order_descendant_iterator old(*this); --*this; return old; }
+
+	// public interface
+	stored_type& operator*() const { return at_top ? const_cast<stored_type&>(*pTop_node->get()) : const_cast<stored_type&>(it.operator *()); }
+	stored_type* operator->() const { return at_top ? const_cast<stored_type*>(pTop_node->get()) : const_cast<stored_type*>(it.operator ->()); }
+	tree_type* node() const { return at_top ? const_cast<tree_type*>(pTop_node) : const_cast<tree_type*>(it.node()); }
+
+	// friends
+	using const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::it;
+	using const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::pTop_node;
+	using const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::at_top;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+    typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::const_post_order_descendant_iterator : public std::iterator<std::bidirectional_iterator_tag, stored_type>
+{
+public:
+	// constructors/destructor
+	const_post_order_descendant_iterator() : pTop_node(0) {}
+	virtual ~const_post_order_descendant_iterator() {}
+	// copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit const_post_order_descendant_iterator(const tree_type* pCalled_node, bool beg); 
+
+public:
+	// overloaded operators
+	const_post_order_descendant_iterator& operator ++(); 
+	const_post_order_descendant_iterator operator ++(int) { const_post_order_descendant_iterator old(*this); ++*this; return old; }
+	const_post_order_descendant_iterator& operator --(); 
+	const_post_order_descendant_iterator operator --(int) { const_post_order_descendant_iterator old(*this); --*this; return old; }
+
+	// public interface
+	const stored_type& operator*() const { return at_top ? *pTop_node->get() : it.operator *(); }
+	const stored_type* operator->() const { return at_top ? pTop_node->get() : it.operator ->(); }
+	const tree_type* node() const { return at_top ? pTop_node : it.node(); }
+
+	// data
+protected:
+	std::stack<typename tree_category_type::const_iterator > node_stack;   
+	typename tree_category_type::const_iterator it;
+	const tree_type* pTop_node;
+	typename container_type::const_reverse_iterator rit;
+	bool at_top;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class sequential_tree<stored_type>;
+    typedef tree_type tr_type;
+		friend typename tr_type;
+		friend bool operator == ( const const_post_order_descendant_iterator& lhs, const const_post_order_descendant_iterator& rhs );
+	#else
+		template<typename T> friend class sequential_tree;
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		friend bool operator ==<> ( const const_post_order_descendant_iterator& lhs, const const_post_order_descendant_iterator& rhs );
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::post_order_descendant_iterator : public tcl::const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>
+{
+public:
+	// constructors/destructor
+	post_order_descendant_iterator() : const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>() {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit post_order_descendant_iterator(const tree_type* pCalled_node, bool beg) : const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>(pCalled_node, beg) { }
+
+public:
+	// overloaded operators
+	post_order_descendant_iterator& operator ++() { ++(*static_cast<const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	post_order_descendant_iterator operator ++(int) { post_order_descendant_iterator old(*this); ++*this; return old; }
+	post_order_descendant_iterator& operator --() { --(*static_cast<const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	post_order_descendant_iterator operator --(int) { post_order_descendant_iterator old(*this); --*this; return old; }
+
+	// public interface
+	stored_type& operator*() const { return at_top ? const_cast<stored_type&>(*pTop_node->get()) : const_cast<stored_type&>(it.operator *()); }
+	stored_type* operator->() const { return at_top ? const_cast<stored_type*>(pTop_node->get()) : const_cast<stored_type*>(it.operator ->()); }
+	tree_type* node() const { return at_top ? const_cast<tree_type*>(pTop_node) : const_cast<tree_type*>(it.node()); }
+
+	// friends
+	using const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::it;
+	using const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::pTop_node;
+	using const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::at_top;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+    typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::const_level_order_descendant_iterator : public std::iterator<std::forward_iterator_tag, stored_type>
+{
+public:
+	// constructors/destructor
+	const_level_order_descendant_iterator() : pTop_node(0), at_top(false) {}
+	virtual ~const_level_order_descendant_iterator() {}
+	// copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit const_level_order_descendant_iterator(const tree_type* pCalled_node, bool beg) : it(beg ? pCalled_node->begin() : pCalled_node->end()), pTop_node(pCalled_node), at_top(beg) {}
+
+public:
+	// overloaded operators
+	const_level_order_descendant_iterator& operator ++();
+	const_level_order_descendant_iterator operator ++(int) { const_level_order_descendant_iterator old(*this); ++*this; return old; }
+
+	// public interface
+	const stored_type& operator*() const { return at_top ? *pTop_node->get() : it.operator *(); }
+	const stored_type* operator->() const { return at_top ? pTop_node->get() : it.operator ->(); }
+	const tree_type* node() const { return at_top ? pTop_node : it.node(); }
+
+	// data
+protected:
+	typename tree_category_type::const_iterator it;
+	std::queue<typename tree_category_type::const_iterator> node_queue;
+	const tree_type* pTop_node;
+	bool at_top;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+    typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+		friend bool operator == (const const_level_order_descendant_iterator& lhs, const const_level_order_descendant_iterator& rhs);
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+		friend bool operator ==<> (const const_level_order_descendant_iterator& lhs, const const_level_order_descendant_iterator& rhs);
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::level_order_descendant_iterator : public tcl::const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>
+{
+public:
+	// constructors/destructor
+	level_order_descendant_iterator() : const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>() {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit level_order_descendant_iterator(const tree_type* const pCalled_node, bool beg) : const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>(pCalled_node, beg) {}
+
+public:
+	// overloaded operators
+	level_order_descendant_iterator& operator ++() { ++(*static_cast<const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	level_order_descendant_iterator operator ++(int) { level_order_descendant_iterator old(*this); ++*this; return old; }
+
+	// public interface
+	stored_type& operator*() const { return at_top ? const_cast<stored_type&>(*pTop_node->get()) : const_cast<stored_type&>(it.operator *()); }
+	stored_type* operator->() const { return at_top ? const_cast<stored_type*>(pTop_node->get()) : const_cast<stored_type*>(it.operator ->()); }
+	tree_type* node() const { return at_top ? const_cast<tree_type*>(pTop_node) : const_cast<tree_type*>(it.node()); }
+
+	// friends
+	using const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::it;
+	using const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::pTop_node;
+	using const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::at_top;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+    typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+	#else
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T, typename U> friend class tree;
+		template<typename T> friend class sequential_tree;
+	#endif
+};
+
+
+#include "descendant_iterator.inl"

+ 222 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_iterator.inl

@@ -0,0 +1,222 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+
+// pre_order_iterator ++()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
+{
+	if (at_top) {  // at top node?
+		at_top = false; // iterator will be used going forward from here
+		it = pTop_node->begin();
+	} else if ( !it.node()->empty() ) { // any children?
+		node_stack.push(it); // yes. push current pos
+		it = it.node()->begin(); // and goto first child
+	} else {
+		++it; // no children. incr to next sibling if present
+		// while stack not empty and no next sibling
+		while ( !node_stack.empty() && it == (node_stack.top()).node()->end() ) {
+			it = node_stack.top(); // pop parent
+			node_stack.pop();
+			++it; // and see if it's got a next sibling
+		}
+	}
+	return *this; 
+}
+
+// pre_order_iterator --()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::operator --()
+{
+	typedef typename tree_category_type::const_iterator iterator_type;
+	if ( it == pTop_node->end() ) { // at end?
+		// yes. is top node empty?
+		if (pTop_node->empty()) {
+			at_top = true;
+			return *this;
+		}
+		//need to set up stack to state just before end
+		rit = pTop_node->children.rbegin(); // going backwards
+		if ( rit != pTop_node->children.rend() ) { // insure there's children
+			if ( !(*rit)->empty() ) { // last node have children?
+				do {  // find the last child of this node
+					++rit; // incr reverse iter..
+					it = iterator_type(rit.base(), (it != pTop_node->end() ? it.node() : pTop_node)); // ..to convert to fwd iter correctly
+					node_stack.push(it); // push parents on the way down
+					rit = it.node()->children.rbegin(); // get last child again
+				} while ( !(*rit)->empty() ); // while last child has children
+			}
+			++rit; // incr reverse iter
+			it = iterator_type(rit.base(), (it != pTop_node->end() ? node() : pTop_node)); // to convert to forward iter correctly
+		}
+	} else { // not at end.
+		if ( it != it.node()->parent()->begin() ) { // is this first sibling?
+			--it; // no.  ok to decr to next sibling
+			if (!it.node()->empty()) { // children present?
+				do { // yes.  get deepest last child
+					node_stack.push(it); // first push current 
+					it = iterator_type(it.node()->children.end(), it.node());
+					--it;  // then go to last child
+				} while ( !it.node()->empty() ); // while children present
+			}
+		} else if (!node_stack.empty()){ // first sibling.  Check for parent
+			it = node_stack.top(); // just need to goto parent
+			node_stack.pop();
+		} else {
+			if (!at_top) { // not at top node?
+				at_top = true;  // set at top (first) node
+			} else {
+				--it;  // decrementing beyond top.  this will make the iterator invalid
+				at_top = false;
+			}
+		}
+	}
+	return *this;
+}
+
+// post_order_iterator constructor
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::const_post_order_descendant_iterator(const tree_type* pCalled_node, bool beg) : pTop_node(pCalled_node), at_top(false)
+{
+	if (!beg) {
+		it = pTop_node->end();
+	} else {
+		it = pCalled_node->begin();  // goto first child
+		if ( it != pTop_node->end()) {
+			if ( !it.node()->empty() ) { // have children of it's own?
+				do {  // goto deepest first child, while pushing parents
+					node_stack.push(it);
+					it = it.node()->begin();
+				} while ( !it.node()->empty() );
+			}
+		} else {
+			// no children.  set top node as current
+			at_top = true;
+		}
+	}
+}
+
+// post_order_iterator ++()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
+{
+	if (at_top) { // at last (called) node?
+		// yes.  
+		at_top = false;
+		it = pTop_node->end();
+		return *this;
+	} else if (pTop_node->empty()) {
+		++it;  // iterator has just traversed past end
+		return *this;
+	}
+
+	const typename tree_category_type::const_iterator it_end = it.node()->parent()->end(); // end sibling
+	++it; // advance to next sibling, if present
+	if ( it != it_end && !it.node()->empty() ) { // next sibling present, and has children?
+		do {  // goto deepest first child while pushing parents
+			node_stack.push(it);
+			it = it.node()->begin();
+		} while ( !it.node()->empty() );
+	} else { // it is past last sibling, or it has no children
+		// if valid it and it has no children, were done
+		if ( !node_stack.empty() && it == (node_stack.top()).node()->end() ) {
+			// it is past last sibling, and pushed parents exist.  move back up to parent
+			it = node_stack.top();
+			node_stack.pop();
+		} else if (node_stack.empty() && it == pTop_node->end()) {
+			// at top node.  
+			at_top = true; // no.  now at top node.
+		}
+	}
+	return *this;
+}
+
+// post_order_iterator --()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::operator --()
+{
+	typedef typename tree_category_type::const_iterator iterator_type;
+	
+	if (at_top) { // at top node
+		at_top = false;
+		typename container_type::const_reverse_iterator rit = pTop_node->children.rbegin();
+		++rit;
+		it = iterator_type(rit.base(), pTop_node); // goto last sibling of top node
+	} else if ( it == pTop_node->end() ) { // at end of descendants?
+		at_top = true;
+	} else { // not at end
+		if ( !it.node()->empty() ) { // children present?
+			typename container_type::const_reverse_iterator rit = it.node()->children.rbegin();
+			node_stack.push(it);
+			++rit; // push parent and go to last child
+			it = iterator_type(rit.base(), it.node());
+		} else { // no children present
+			if ( it != it.node()->parent()->begin() ) { // at first sibling?
+				--it; // no.  just goto prev sibling
+			} else { // at first sibling. work our way up until not first sibling
+				while ( !node_stack.empty() && it == node_stack.top().node()->begin())
+				{
+					it = node_stack.top();
+					node_stack.pop();
+				}
+				--it; // then goto prev sibling
+			}
+		}
+	}
+	return *this;
+}
+
+// level_order_iterator ++()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
+{
+	if (at_top) {  // at top node?
+		// yes.  
+		at_top = false;
+		it = pTop_node->begin();
+		return *this;
+	}
+
+	const typename tree_category_type::const_iterator it_end = it.node()->parent()->end(); 
+	node_queue.push(it); // push current pos node in queue
+	++it;  // and goto next sibling if present
+
+	if ( it == it_end ) { // past last sibling?  If not, we're done.
+		while ( !node_queue.empty() ) { // yes. Insure queue not empty
+			it = node_queue.front(); // pull pos off queue
+			node_queue.pop(); // this should be the start pos of level just traversed
+			if ( !it.node()->empty() ) { // have children?
+				it = node()->begin(); // yes. descend to start of next level
+				break;
+			} else if ( node_queue.empty() ) { // no children.  is queue empty?
+				it = pTop_node->end(); // yes. at end
+				return *this;
+			}
+		} 
+	}
+	return *this;
+}
+

+ 296 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_node_iterator.h

@@ -0,0 +1,296 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "child_node_iterator.h"
+#include <set>
+#include <stack>
+#include <queue>
+#include <algorithm>
+
+namespace tcl 
+{
+	template<typename T, typename U, typename V, typename W> class const_pre_order_descendant_node_iterator;
+	template<typename T, typename U, typename V, typename W> class pre_order_descendant_node_iterator;
+	template<typename T, typename U, typename V, typename W> class const_post_order_descendant_node_iterator;
+	template<typename T, typename U, typename V, typename W> class post_order_descendant_node_iterator;
+	template<typename T, typename U, typename V, typename W> class const_level_order_descendant_node_iterator;
+	template<typename T, typename U, typename V, typename W> class level_order_descendant_node_iterator;
+
+	// comparison operators
+	template<typename T, typename U, typename V, typename W> bool operator == (const const_pre_order_descendant_node_iterator<T, U, V, W>& lhs, const const_pre_order_descendant_node_iterator<T, U, V, W>& rhs) { return lhs.it == rhs.it && lhs.at_top == rhs.at_top; }
+	template<typename T, typename U, typename V, typename W> bool operator != (const const_pre_order_descendant_node_iterator<T, U, V, W>& lhs, const const_pre_order_descendant_node_iterator<T, U, V, W>& rhs) { return !(lhs == rhs); }
+	template<typename T, typename U, typename V, typename W> bool operator == (const const_post_order_descendant_node_iterator<T, U, V, W>& lhs, const const_post_order_descendant_node_iterator<T, U, V, W>& rhs) { return lhs.it == rhs.it && lhs.at_top == rhs.at_top; }
+	template<typename T, typename U, typename V, typename W> bool operator != (const const_post_order_descendant_node_iterator<T, U, V, W>& lhs, const const_post_order_descendant_node_iterator<T, U, V, W>& rhs) { return !(lhs == rhs); }
+	template<typename T, typename U, typename V, typename W> bool operator == (const const_level_order_descendant_node_iterator<T, U, V, W>& lhs, const const_level_order_descendant_node_iterator<T, U, V, W>& rhs) { return lhs.it == rhs.it && lhs.at_top == rhs.at_top; }
+	template<typename T, typename U, typename V, typename W> bool operator != (const const_level_order_descendant_node_iterator<T, U, V, W>& lhs, const const_level_order_descendant_node_iterator<T, U, V, W>& rhs) { return !(lhs == rhs); }
+
+}
+
+/************************************************************************/
+/* descendant iterators                                                 */
+/************************************************************************/
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::const_pre_order_descendant_node_iterator : public std::iterator<std::bidirectional_iterator_tag, tree_type>
+{
+public:
+	// constructors/destructor
+	const_pre_order_descendant_node_iterator() : pTop_node(0), at_top(false) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit const_pre_order_descendant_node_iterator(const tree_type* pCalled_node, bool beg) : it(beg ? pCalled_node->node_begin() : pCalled_node->node_end()), pTop_node(pCalled_node), at_top(beg) {}
+
+public:
+	// overloaded operators
+	const_pre_order_descendant_node_iterator& operator ++(); 
+	const_pre_order_descendant_node_iterator operator ++(int) { const_pre_order_descendant_node_iterator old(*this); ++*this; return old; }
+	const_pre_order_descendant_node_iterator& operator --();
+	const_pre_order_descendant_node_iterator operator --(int) { const_pre_order_descendant_node_iterator old(*this); --*this; return old; }
+	const tree_type& operator*() const { return at_top ? *pTop_node : it.operator *(); }
+	const tree_type* operator->() const { return at_top ? pTop_node : it.operator ->(); }
+
+	// data
+protected:
+	typename tree_category_type::const_node_iterator it;
+	std::stack<typename tree_category_type::const_node_iterator> node_stack;   
+	const tree_type* pTop_node;
+	typename container_type::const_reverse_iterator rit;
+	bool at_top;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+		friend bool operator == (const const_pre_order_descendant_node_iterator& lhs, const const_pre_order_descendant_node_iterator& rhs);
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+		friend bool operator ==<> (const const_pre_order_descendant_node_iterator& lhs, const const_pre_order_descendant_node_iterator& rhs);
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::pre_order_descendant_node_iterator : public tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>
+{
+public:
+	// constructors/destructor
+	pre_order_descendant_node_iterator() : const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>() {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit pre_order_descendant_node_iterator(const tree_type* const pCalled_node, bool beg) : const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>(pCalled_node, beg) {}
+
+public:
+	// overloaded operators
+	pre_order_descendant_node_iterator& operator ++() { ++(*static_cast<const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	pre_order_descendant_node_iterator operator ++(int) { pre_order_descendant_node_iterator old(*this); ++*this; return old; }
+	pre_order_descendant_node_iterator& operator --() { --(*static_cast<const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	pre_order_descendant_node_iterator operator --(int) { pre_order_descendant_node_iterator old(*this); --*this; return old; }
+
+	// public interface
+	tree_type& operator*() const { return at_top ? const_cast<tree_type&>(*pTop_node) : const_cast<tree_type&>(it.operator *()); }
+	tree_type* operator->() const { return at_top ? const_cast<tree_type*>(pTop_node) : const_cast<tree_type*>(it.operator ->()); }
+
+	// friends
+	using const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::it;
+	using const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::pTop_node;
+	using const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::at_top;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+	#endif
+};
+
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::const_post_order_descendant_node_iterator : public std::iterator<std::bidirectional_iterator_tag, tree_type>
+{
+public:
+	// constructors/destructor
+	const_post_order_descendant_node_iterator() : pTop_node(0), at_top(false) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit const_post_order_descendant_node_iterator(const tree_type* pCalled_node, bool beg); 
+
+public:
+	// overloaded operators
+	const_post_order_descendant_node_iterator& operator ++(); 
+	const_post_order_descendant_node_iterator operator ++(int) { const_post_order_descendant_node_iterator old(*this); ++*this; return old; }
+	const_post_order_descendant_node_iterator& operator --(); 
+	const_post_order_descendant_node_iterator operator --(int) { const_post_order_descendant_node_iterator old(*this); --*this; return old; }
+
+	// public interface
+	const tree_type& operator*() const { return at_top ? *pTop_node : it.operator *(); }
+	const tree_type* operator->() const { return at_top ? pTop_node : it.operator ->(); }
+
+	// data
+protected:
+	std::stack<typename tree_category_type::const_node_iterator > node_stack;   
+	typename tree_category_type::const_node_iterator it;
+	const tree_type* pTop_node;
+	typename container_type::const_reverse_iterator rit;
+	bool at_top;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+		friend bool operator == (const const_post_order_descendant_node_iterator& lhs, const const_post_order_descendant_node_iterator& rhs);
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+		friend bool operator ==<> (const const_post_order_descendant_node_iterator& lhs, const const_post_order_descendant_node_iterator& rhs);
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::post_order_descendant_node_iterator : public tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>
+{
+public:
+	// constructors/destructor
+	post_order_descendant_node_iterator() : const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>() {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit post_order_descendant_node_iterator(const tree_type* pCalled_node, bool beg) : const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>(pCalled_node, beg) { }
+
+public:
+	// overloaded operators
+	post_order_descendant_node_iterator& operator ++() { ++(*static_cast<const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	post_order_descendant_node_iterator operator ++(int) { post_order_descendant_node_iterator old(*this); ++*this; return old; }
+	post_order_descendant_node_iterator& operator --() { --(*static_cast<const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	post_order_descendant_node_iterator operator --(int) { post_order_descendant_node_iterator old(*this); --*this; return old; }
+
+	// public interface
+	tree_type& operator*() const { return at_top ? const_cast<tree_type&>(*pTop_node) : const_cast<tree_type&>(it.operator *()); }
+	tree_type* operator->() const { return at_top ? const_cast<tree_type*>(pTop_node) : const_cast<tree_type*>(it.operator ->()); }
+
+	// friends
+	using const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::it;
+	using const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::pTop_node;
+	using const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::at_top;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+	#endif
+};
+
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::const_level_order_descendant_node_iterator : public std::iterator<std::forward_iterator_tag, tree_type>
+{
+public:
+	// constructors/destructor
+	const_level_order_descendant_node_iterator() : pTop_node(0), at_top(false) {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit const_level_order_descendant_node_iterator(const tree_type* pCalled_node, bool beg) : it(beg ? pCalled_node->node_begin() : pCalled_node->node_end()), pTop_node(pCalled_node), at_top(beg) {}
+
+public:
+	// overloaded operators
+	const_level_order_descendant_node_iterator& operator ++();
+	const_level_order_descendant_node_iterator operator ++(int) { const_level_order_descendant_node_iterator old(*this); ++*this; return old; }
+
+	// public interface
+	const tree_type& operator*() const { return at_top ? *pTop_node : it.operator *(); }
+	const tree_type* operator->() const { return at_top ? pTop_node : it.operator ->(); }
+
+	// data
+protected:
+	typename tree_category_type::const_node_iterator it;
+	std::queue<typename tree_category_type::const_node_iterator> node_queue;
+	const tree_type* pTop_node;
+	bool at_top;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+		friend bool operator == (const const_level_order_descendant_node_iterator& lhs, const const_level_order_descendant_node_iterator& rhs);
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+		friend bool operator ==<> (const const_level_order_descendant_node_iterator& lhs, const const_level_order_descendant_node_iterator& rhs);
+	#endif
+};
+
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+class tcl::level_order_descendant_node_iterator : public tcl::const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>
+{
+public:
+	// constructors/destructor
+	level_order_descendant_node_iterator() : const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>() {}
+	// destructor, copy constructor, and assignment operator will be compiler generated correctly
+protected:
+	explicit level_order_descendant_node_iterator(const tree_type* pCalled_node, bool beg) : const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>(pCalled_node, beg) {}
+
+public:
+	// overloaded operators
+	level_order_descendant_node_iterator& operator ++() { ++(*static_cast<const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>*>(this)); return *this; }
+	level_order_descendant_node_iterator operator ++(int) { level_order_descendant_node_iterator old(*this); ++*this; return old; }
+
+	// public interface
+	tree_type& operator*() const { return at_top ? const_cast<tree_type&>(*pTop_node) : const_cast<tree_type&>(it.operator *()); }
+	tree_type* operator->() const { return at_top ? const_cast<tree_type*>(pTop_node) : const_cast<tree_type*>(it.operator ->()); }
+
+	// friends
+	using const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::it;
+	using const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::pTop_node;
+	using const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::at_top;
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		typedef tree_type tr_type;
+		friend typename tr_type;
+		friend class sequential_tree<stored_type>;
+	#else
+		template<typename T, typename U> friend class tree;
+		template<typename T, typename U> friend class multitree;
+		template<typename T, typename U, typename V> friend class unique_tree;
+		template<typename T> friend class sequential_tree;
+	#endif
+};
+
+
+#include "descendant_node_iterator.inl"

+ 221 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/descendant_node_iterator.inl

@@ -0,0 +1,221 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+
+// pre_order_iterator ++()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
+{
+	if (at_top) {  // at top node?
+		at_top = false; // iterator will be used going forward from here
+		it = pTop_node->node_begin();
+	} else if ( !it->empty() ) { // any children?
+		node_stack.push(it); // yes. push current pos
+		it = it->node_begin(); // and goto first child
+	} else {
+		++it; // no children. incr to next sibling if present
+		// while stack not empty and no next sibling
+		while ( !node_stack.empty() && it == (node_stack.top())->node_end() ) {
+			it = node_stack.top(); // pop parent
+			node_stack.pop();
+			++it; // and see if it's got a next sibling
+		}
+	}
+	return *this; 
+}
+
+// pre_order_iterator --()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator --()
+{
+	typedef typename tree_category_type::const_node_iterator iterator_type;
+	if ( it == pTop_node->node_end() ) { // at end?
+		// yes. is top node empty?
+		if (pTop_node->empty()) {
+			at_top = true;
+			return *this;
+		}
+		// yes. need to set up stack to state just before end
+		rit = pTop_node->children.rbegin(); // going backwards
+		if ( rit != pTop_node->children.rend() ) { // insure there's children
+			if ( !(*rit)->empty() ) { // last node have children?
+				do {  // find the last child of this node
+					++rit; // incr reverse iter..
+					it = iterator_type(rit.base(), (it != pTop_node->node_end() ? &(*it) : pTop_node)); // ..to convert to fwd iter correctly
+					node_stack.push(it); // push parents on the way down
+					rit = it->children.rbegin(); // get last child again
+				} while ( !(*rit)->empty() ); // while last child has children
+			}
+			++rit; // incr reverse iter
+			it = iterator_type(rit.base(), (it != pTop_node->node_end() ? &(*it) : pTop_node)); // to convert to forward iter correctly
+		}
+	} else { // not at end.
+		if ( it != it->parent()->node_begin() ) { // is this first sibling?
+			--it; // no.  ok to decr to next sibling
+			if (!it->empty()) { // children present?
+				do { // yes.  get deepest last child
+					node_stack.push(it); // first push current 
+					it = iterator_type(it->children.end(), &(*it));
+					--it;  // then go to last child
+				} while ( !it->empty() ); // while children present
+			}
+		} else if (!node_stack.empty()) { // first sibling.  Check for parent
+			it = node_stack.top(); // just need to goto parent
+			node_stack.pop();
+		} else {
+			if (!at_top) { // not at top node?
+				at_top = true;  // set at top (first) node
+			} else {
+				--it;  // decrementing beyond top.  this will make the iterator invalid
+				at_top = false;
+			}
+		}
+	}
+	return *this;
+}
+
+// post_order_iterator constructor
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::const_post_order_descendant_node_iterator(const tree_type* pCalled_node, bool beg) : pTop_node(pCalled_node), at_top(false)
+{
+	if (!beg) {
+		it = pTop_node->node_end();
+	} else {
+		it = pTop_node->node_begin(); // goto first child
+		if ( it != pTop_node->node_end()) {
+			if ( !it->empty() ) { // have children of it's own?
+				do {  // goto deepest first child, while pushing parents
+					node_stack.push(it);
+					it = it->node_begin();
+				} while ( !it->empty() );
+			}
+		} else {
+			// no children.  set top node as current
+			at_top = true;
+		}
+	}
+}
+
+// post_order_iterator ++()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
+{
+	if (at_top) { // at last (called) node?
+		// yes. 
+		at_top = false;
+		it = pTop_node->node_end();
+		return *this;
+	} else if (pTop_node->empty()) {
+		++it;  // iterator has just traversed past end
+		return *this;
+	}
+
+	const typename tree_category_type::const_node_iterator it_end = it->parent()->node_end(); // end sibling
+	++it; // advance to next sibling, if present
+	if ( it != it_end && !it->empty() ) { // next sibling present, and has children?
+		do {  // goto deepest first child while pushing parents
+			node_stack.push(it);
+			it = it->node_begin();
+		} while ( !it->empty() );
+	} else { // it is past last sibling, or it has no children
+		// if valid it and it has no childrent, were done
+		if ( !node_stack.empty() && it == node_stack.top()->node_end() ) {
+			// it is past last sibling, and pushed parents exist.  move back up to parent
+			it = node_stack.top();
+			node_stack.pop();
+		} else if (node_stack.empty() && it == pTop_node->node_end()) {
+			// at top node. 
+			at_top = true;  
+		}
+	}
+	return *this;
+}
+
+// post_order_iterator --()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator --()
+{
+	typedef typename tree_category_type::const_node_iterator iterator_type;
+
+	if (at_top) { // at top node
+		at_top = false;
+		typename container_type::const_reverse_iterator rit = pTop_node->children.rbegin();
+		++rit;
+		it = iterator_type(rit.base(), pTop_node); // goto last sibling of top node
+	} else if ( it == pTop_node->node_end() ) { // at end?
+		at_top = true;
+	} else { // not at end
+		if ( !it->empty() ) { // children present?
+			typename container_type::const_reverse_iterator rit = it->children.rbegin();
+			node_stack.push(it);
+			++rit; // push parent and go to last child
+			it = iterator_type(rit.base(), &(*it));
+		} else { // no children present
+			if ( it != it->parent()->node_begin() ) { // at first sibling?
+				--it; // no.  just goto prev sibling
+			} else { // at first sibling. work our way up until not first sibling
+				while ( !node_stack.empty() && it == node_stack.top()->node_begin())
+				{
+					it = node_stack.top();
+					node_stack.pop();
+				}
+				--it; // then goto prev sibling
+			}
+		}
+	}
+	return *this;
+}
+
+// level_order_iterator ++()
+template<typename stored_type, typename tree_type, typename container_type, typename tree_category_type>
+tcl::const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>& tcl::const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_category_type>::operator ++()
+{
+	if (at_top) { // at top?
+		// yes.  
+		at_top = false;
+		it = pTop_node->node_begin();
+		return *this;
+	}
+
+	const typename tree_category_type::const_node_iterator it_end = it->parent()->node_end(); 
+	node_queue.push(it); // push current pos node in queue
+	++it;  // and goto next sibling if present
+
+	if ( it == it_end ) { // past last sibling?  If not, we're done.
+		while ( !node_queue.empty() ) { // yes. Insure queue not empty
+			it = node_queue.front(); // pull pos off queue
+			node_queue.pop(); // this should be the start pos of level just traversed
+			if ( !it->empty() ) { // have children?
+				it = it->node_begin(); // yes. descend to start of next level
+				break;
+			} else if ( node_queue.empty() ) { // no children.  is queue empty?
+				it = pTop_node->node_end(); // yes. at end
+				return *this;
+			}
+		} 
+	}
+	return *this;
+}

+ 135 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/multitree.h

@@ -0,0 +1,135 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once 
+#include "associative_tree.h"
+#include <set>
+
+namespace tcl
+{
+	// forward declaration for deref comparison functor
+	template<typename stored_type, typename node_compare_type > class multitree;
+
+	// deref comparison functor, derive from binary function per Scott Meyer
+	template<typename stored_type, typename node_compare_type >
+	struct multitree_deref_less : public std::binary_function<const multitree<stored_type, node_compare_type>*, const multitree<stored_type, node_compare_type>*, bool>
+	{
+		bool operator () (const multitree<stored_type, node_compare_type>* lhs, const multitree<stored_type, node_compare_type>* rhs) const
+		{
+			// call < on actual object
+			return node_compare_type()(*lhs->get(), *rhs->get());
+		}
+	};
+}
+
+
+
+// node object type.  forwards most operations to base_tree_type, 
+// instanciates base_tree_type with type of container (set of unique_tree ptrs) to use for node and key comparisons
+template<typename stored_type, typename node_compare_type = std::less<stored_type> >
+class tcl::multitree : public tcl::associative_tree<stored_type, tcl::multitree<stored_type, node_compare_type>,  std::multiset<tcl::multitree<stored_type, node_compare_type>*, tcl::multitree_deref_less<stored_type, node_compare_type> > >
+{
+public:
+	// typedefs
+	typedef multitree<stored_type, node_compare_type> tree_type;
+	typedef multitree_deref_less<stored_type, node_compare_type> key_compare;
+	typedef multitree_deref_less<stored_type, node_compare_type> value_compare;
+	typedef std::multiset<tree_type*, key_compare> container_type;
+	typedef basic_tree<stored_type, tree_type, container_type> basic_tree_type;
+	typedef associative_tree<stored_type, tree_type, container_type> associative_tree_type;
+
+	// constructors/destructor
+	explicit multitree( const stored_type& value = stored_type() ) : associative_tree_type(value) {}
+	template<typename iterator_type> multitree(iterator_type it_beg, iterator_type it_end, const stored_type& value = stored_type()) : associative_tree_type(value) { while (it_beg != it_end) { insert(*it_beg); ++it_beg; } }
+	multitree( const tree_type& rhs ); // copy constructor
+	~multitree() { associative_tree_type::clear(); }
+
+ 	// assignment operator
+	tree_type& operator = (const tree_type& rhs);
+
+	// public interface
+public:
+	typename associative_tree_type::iterator insert(const stored_type& value) { return associative_tree_type::insert(value, this); }
+	typename associative_tree_type::iterator insert(const typename associative_tree_type::const_iterator pos, const stored_type& value) { return associative_tree_type::insert(pos, value, this); }
+	typename associative_tree_type::iterator insert(const tree_type& tree_obj ) { return associative_tree_type::insert(tree_obj, this); }
+	typename associative_tree_type::iterator insert(const typename associative_tree_type::const_iterator pos, const tree_type& tree_obj) { return associative_tree_type::insert(pos, tree_obj, this); }
+	#if !defined(_MSC_VER) || _MSC_VER >= 1300 // insert range not available for VC6
+		template<typename iterator_type> void insert(iterator_type it_beg, iterator_type it_end) { while ( it_beg != it_end ) insert(*it_beg++); }
+	#endif
+	void swap(tree_type& rhs);
+
+	// descendant element iterator accessors
+	typedef typename associative_tree_type::post_order_iterator post_order_iterator_type;
+	typedef typename associative_tree_type::const_post_order_iterator const_post_order_iterator_type;
+	typedef typename associative_tree_type::pre_order_iterator pre_order_iterator_type;
+	typedef typename associative_tree_type::const_pre_order_iterator const_pre_order_iterator_type;
+	typedef typename associative_tree_type::level_order_iterator level_order_iterator_type;
+	typedef typename associative_tree_type::const_level_order_iterator const_level_order_iterator_type;
+
+	pre_order_iterator_type pre_order_begin() { return pre_order_iterator_type(this, true); }
+	pre_order_iterator_type pre_order_end() { return pre_order_iterator_type(this, false); }
+	const_pre_order_iterator_type pre_order_begin() const { return const_pre_order_iterator_type(this, true); }
+	const_pre_order_iterator_type pre_order_end() const { return const_pre_order_iterator_type(this, false); }
+	post_order_iterator_type post_order_begin() { return post_order_iterator_type(this, true); }
+	post_order_iterator_type post_order_end() { return post_order_iterator_type(this, false); }
+	const_post_order_iterator_type post_order_begin() const { return const_post_order_iterator_type(this, true); }
+	const_post_order_iterator_type post_order_end() const { return const_post_order_iterator_type(this, false); }
+	level_order_iterator_type level_order_begin() { return level_order_iterator_type(this, true); }
+	level_order_iterator_type level_order_end() { return level_order_iterator_type(this, false); }
+	const_level_order_iterator_type level_order_begin() const { return const_level_order_iterator_type(this, true); }
+	const_level_order_iterator_type level_order_end() const { return const_level_order_iterator_type(this, false); }
+
+	// descendant node iterator accessors
+	typedef typename associative_tree_type::pre_order_node_iterator pre_order_node_iterator_type;
+	typedef typename associative_tree_type::const_pre_order_node_iterator const_pre_order_node_iterator_type;
+	typedef typename associative_tree_type::post_order_node_iterator post_order_node_iterator_type;
+	typedef typename associative_tree_type::const_post_order_node_iterator const_post_order_node_iterator_type;
+	typedef typename associative_tree_type::level_order_node_iterator level_order_node_iterator_type;
+	typedef typename associative_tree_type::const_level_order_node_iterator const_level_order_node_iterator_type;
+
+	pre_order_node_iterator_type pre_order_node_begin() { return pre_order_node_iterator_type(this, true); }
+	pre_order_node_iterator_type pre_order_node_end() { return pre_order_node_iterator_type(this, false); }
+	const_pre_order_node_iterator_type pre_order_node_begin() const { return const_pre_order_node_iterator_type(this, true); }
+	const_pre_order_node_iterator_type pre_order_node_end() const { return const_pre_order_node_iterator_type(this, false); }
+	post_order_node_iterator_type post_order_node_begin() { return post_order_node_iterator_type(this, true); }
+	post_order_node_iterator_type post_order_node_end() { return post_order_node_iterator_type(this, false); }
+	const_post_order_node_iterator_type post_order_node_begin() const { return const_post_order_node_iterator_type(this, true); }
+	const_post_order_node_iterator_type post_order_node_end() const { return const_post_order_node_iterator_type(this, false); }
+	level_order_node_iterator_type level_order_node_begin() { return level_order_node_iterator_type(this, true); }
+	level_order_node_iterator_type level_order_node_end() { return level_order_node_iterator_type(this, false); }
+	const_level_order_node_iterator_type level_order_node_begin() const { return const_level_order_node_iterator_type(this, true); }
+	const_level_order_node_iterator_type level_order_node_end() const { return const_level_order_node_iterator_type(this, false); }
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class basic_tree<stored_type, tree_type, container_type>;
+	#else
+		template<typename T, typename U, typename V> friend class basic_tree;
+	#endif
+};
+
+
+#include "multitree.inl"

+ 76 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/multitree.inl

@@ -0,0 +1,76 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+
+// copy constructor
+template<typename stored_type, typename node_compare_type>
+tcl::multitree<stored_type, node_compare_type>::multitree( const tree_type& rhs ) : associative_tree_type(rhs)
+{
+	typename associative_tree_type::const_iterator it = rhs.begin();
+	const typename associative_tree_type::const_iterator it_end = rhs.end();
+	for ( ; it != it_end; ++it )  // do deep copy by inserting children (and descendants)
+	{
+		associative_tree_type::insert(*it.node(), this);
+	}
+}
+
+
+// assignment operator
+template<typename stored_type, typename node_compare_type>
+tcl::multitree<stored_type, node_compare_type>& 
+tcl::multitree<stored_type, node_compare_type>::operator = (const tree_type& rhs)
+{
+	if (!associative_tree_type::is_root()) // can assign only to root node
+		return *this;
+
+	if ( this == &rhs ) // check for self assignment
+		return *this;
+
+	associative_tree_type::clear();
+	basic_tree_type::operator =(rhs);  // call base class operation
+
+	typename associative_tree_type::const_iterator it = rhs.begin();
+	const typename associative_tree_type::const_iterator it_end = rhs.end();
+	for ( ; it != it_end; ++it )  // insert children and descendants
+	{
+		associative_tree_type::insert(*it.node(), this);
+	}
+	return *this;
+}
+
+// swap
+template<typename stored_type, typename node_compare_type>
+void tcl::multitree<stored_type, node_compare_type>::swap(tree_type& rhs)
+{
+	tree_type temp(*this);
+
+	associative_tree_type::clear();
+	*this = rhs;
+
+	rhs.clear();
+	rhs = temp;
+}
+

+ 111 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/ordered_iterator.h

@@ -0,0 +1,111 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "child_iterator.h"
+
+namespace tcl 
+{
+	template<typename stored_type, typename node_compare_type, typename node_order_compare_type> class unique_tree;
+	template< typename stored_type, typename tree_type,  typename container_type > class associative_tree;
+	template<typename tree_type, typename node_order_compare_type> struct deref_ordered_compare;
+	template<typename stored_type, typename node_compare_type, typename node_order_compare_type > struct unique_tree_deref_less;
+
+	template<typename T, typename U, typename V> class const_unique_tree_ordered_iterator;
+	template<typename T, typename U, typename V> class unique_tree_ordered_iterator;
+
+	// comparison operators
+	template<typename T, typename U, typename V> bool operator == ( const const_unique_tree_ordered_iterator<T, U, V>& lhs, const const_unique_tree_ordered_iterator<T, U, V>& rhs ) { return lhs.it == rhs.it; }
+	template<typename T, typename U, typename V> bool operator != ( const const_unique_tree_ordered_iterator<T, U, V>& lhs, const const_unique_tree_ordered_iterator<T, U, V>& rhs ) { return !(lhs == rhs); }
+}
+
+
+/************************************************************************/
+/* ordered iterators (for unique_tree)                                  */
+/************************************************************************/
+
+
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+class tcl::const_unique_tree_ordered_iterator : public std::iterator<std::bidirectional_iterator_tag, stored_type>
+{
+protected:
+	// typedefs
+	typedef unique_tree<stored_type, node_compare_type, node_order_compare_type> tree_type;
+	typedef std::multiset<tree_type*, deref_ordered_compare<tree_type, node_order_compare_type> > ordered_container_type;
+
+public:
+	// constructors/destructor
+	const_unique_tree_ordered_iterator() {}
+	explicit const_unique_tree_ordered_iterator(typename ordered_container_type::const_iterator iter) : it(iter) {}
+	virtual ~const_unique_tree_ordered_iterator() {}
+
+	// overloaded operators
+	const_unique_tree_ordered_iterator& operator ++() { ++it; return *this; }
+	const_unique_tree_ordered_iterator operator ++(int) { const_unique_tree_ordered_iterator old(*this); ++*this; return old; }
+	const_unique_tree_ordered_iterator& operator --() { --it; return *this; }
+	const_unique_tree_ordered_iterator operator --(int) { const_unique_tree_ordered_iterator old(*this); --*this; return old; }
+	const stored_type& operator*() const { return  *(*it)->get(); }
+	const stored_type* operator->() const { return (*it)->get(); }
+
+	const tree_type* node() const { return *it; }
+
+	// data
+protected:
+	typename ordered_container_type::const_iterator it;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend bool operator == ( const const_unique_tree_ordered_iterator& lhs, const const_unique_tree_ordered_iterator& rhs );
+	#else
+		friend bool operator ==<> ( const const_unique_tree_ordered_iterator& lhs, const const_unique_tree_ordered_iterator& rhs );
+	#endif
+};
+
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+class tcl::unique_tree_ordered_iterator : public tcl::const_unique_tree_ordered_iterator<stored_type, node_compare_type, node_order_compare_type>
+{
+	// typedefs
+	typedef unique_tree<stored_type, node_compare_type, node_order_compare_type> tree_type;
+	typedef std::multiset<tree_type*, deref_ordered_compare<tree_type, node_order_compare_type> > ordered_container_type;
+	using const_unique_tree_ordered_iterator<stored_type, node_compare_type, node_order_compare_type>::it;
+
+public:
+	// constructors/destructor
+	unique_tree_ordered_iterator() {}
+	explicit unique_tree_ordered_iterator(const typename const_unique_tree_ordered_iterator<stored_type, node_compare_type, node_order_compare_type>::ordered_container_type::const_iterator& iter) 
+		: const_unique_tree_ordered_iterator<stored_type, node_compare_type, node_order_compare_type>(iter) {}
+
+	// overloaded operators
+	stored_type& operator*() const { return *(*it)->get(); }
+	stored_type* operator->() const { return (*it)->get(); }
+	unique_tree_ordered_iterator& operator ++() { ++it; return *this; }
+	unique_tree_ordered_iterator operator ++(int) { unique_tree_ordered_iterator old(*this); ++*this; return old; }
+	unique_tree_ordered_iterator& operator --() { --it; return *this; }
+	unique_tree_ordered_iterator operator --(int) { unique_tree_ordered_iterator old(*this); --*this; return old; }
+
+	tree_type* node() const { return *it; }
+};
+

+ 114 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/populateAlphabet.h

@@ -0,0 +1,114 @@
+#pragma once
+#include <cassert>
+#include <iostream>
+
+template<typename TreeType>
+void populateAlphabet(TreeType& alphaTree, bool duplicateVowels = false, bool verbose = false)
+{
+	// create a child iterator
+	typename TreeType::iterator it;  
+
+	// insert first node, A
+	it = alphaTree.insert(Alpha('A'));
+	assert(it != alphaTree.end() && it->getLetter() == 'A' );
+	if (duplicateVowels) {
+		// try to insert another A.  Should fail for tree & unique_tree
+		it = alphaTree.insert(Alpha('A'));
+		if ( it == alphaTree.end() && verbose)
+			std::cout << alphaTree.get()->getLetter() << ": Couldn't insert second A." << std::endl;
+	}
+
+	// insert D and E under A
+	it = alphaTree.begin();
+	assert(it != alphaTree.end() && it->getLetter() == 'A');
+	typename TreeType::iterator child_it = it.node()->insert(Alpha('D'));
+	assert(child_it != it.node()->end() && child_it->getLetter() == 'D');  
+	it.node()->insert(Alpha('E'));
+
+
+	it = it.node()->begin();
+	// insert  J under D
+	it.node()->insert(Alpha('J'));
+	// insert K under D and remember inserted node
+	child_it = it.node()->insert(Alpha('K'));
+	assert(child_it != it.node()->end() && child_it->getLetter() == 'K');
+	// insert R and S under K
+	child_it.node()->insert(Alpha('R'));
+	child_it.node()->insert(Alpha('S'));
+
+	// increment it (now at D) to point to E
+	++it;
+	// insert L under E
+	it.node()->insert(Alpha('L'));
+
+	it = alphaTree.insert(Alpha('B'));
+	// insert second E and F under B
+	if (duplicateVowels) {
+		child_it = it.node()->insert(Alpha('E'));  // should fail for unique_tree
+		if ( child_it == it.node()->end() && verbose)
+			std::cout << alphaTree.get()->getLetter() << ": Couldn't insert second E." << std::endl;
+	}
+	child_it = it.node()->insert(Alpha('F'));
+	// insert M under F
+	it = child_it;
+	child_it = it.node()->insert(Alpha('M'));
+	// insert T and U under M
+	child_it.node()->insert(Alpha('T'));
+	child_it.node()->insert(Alpha('U'));
+
+	// insert N under F  (it still points to F)
+	child_it = it.node()->insert(Alpha('N'));
+	// insert second U and V under N
+	if (duplicateVowels) {
+		if ( child_it.node()->insert(Alpha('U')) == child_it.node()->end() && verbose) // should fail for unique_tree
+			std::cout << alphaTree.get()->getLetter() << ": Couldn't insert second U." << std::endl;
+	}
+
+	child_it.node()->insert(Alpha('V'));
+
+	it = alphaTree.insert(Alpha('C'));
+	// insert G and H under C
+	it.node()->insert(Alpha('G'));
+	child_it = it.node()->insert(Alpha('H'));
+	// insert O under H
+	it = child_it;
+	child_it = it.node()->insert(Alpha('O'));
+	if (duplicateVowels) {
+		// try to insert another O
+		child_it = it.node()->insert(Alpha('O')); // should fail for tree/unique_tree
+		if ( child_it == it.node()->end() && verbose)
+			std::cout << alphaTree.get()->getLetter() << ": Couldn't insert second O." << std::endl;
+	}
+
+	child_it = it.node()->begin();
+	assert(child_it != it.node()->end() && child_it->getLetter() == 'O');
+	// insert W under O
+	child_it.node()->insert(Alpha('W'));
+	// insert P under H
+	it.node()->insert(Alpha('P'));
+
+	// insert I under C using parent of H (which is C)
+	child_it = it.node()->parent()->insert(Alpha('I'));
+	assert(child_it->getLetter() == 'I');
+	// insert second I under I
+	it = child_it;
+	if (duplicateVowels) {
+		child_it = it.node()->insert(Alpha('I'));  // should fail for unique tree
+		if ( child_it == it.node()->end() && verbose)
+			std::cout << alphaTree.get()->getLetter() << ": Couldn't insert second I." << std::endl;
+	}
+
+	// insert Q under original I
+	child_it = it.node()->insert(Alpha('Q'));
+	// insert X under Q
+	it = child_it;
+	child_it = it.node()->insert(Alpha('X'));
+	// insert Y and Z under X
+	child_it.node()->insert(Alpha('Y'));
+	child_it.node()->insert(Alpha('Z'));
+
+  if (verbose)
+	  std::cout << std::endl << std::endl;
+}
+
+

+ 124 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/reverse_iterator.h

@@ -0,0 +1,124 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "child_iterator.h"
+#include <iterator>
+
+namespace tcl 
+{
+	template<typename stored_type, typename tree_type, typename container_type> class associative_reverse_iterator;
+
+	template<typename T, typename U, typename V> class const_associative_reverse_iterator;
+	template<typename T, typename U, typename V> class associative_reverse_iterator;
+	template<typename T, typename U, typename V> class const_sequential_reverse_iterator;
+	template<typename T, typename U, typename V> class const_sequential_reverse_iterator;
+}
+
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_associative_reverse_iterator : public tcl::const_associative_iterator<stored_type, tree_type, container_type>
+{
+	typedef const_associative_iterator<stored_type, tree_type, container_type> associative_iterator_type;
+public:
+	const_associative_reverse_iterator() : associative_iterator_type() {}
+	explicit const_associative_reverse_iterator(const associative_iterator_type& _it) : associative_iterator_type(_it) {}
+	const_associative_reverse_iterator(associative_reverse_iterator<stored_type, tree_type, container_type>& _it) : associative_iterator_type(_it.it) {}
+
+	const stored_type& operator*() const { associative_iterator_type tmp(*this);  return (*--tmp); }
+	const stored_type* operator->() const { associative_iterator_type tmp(*this); --tmp; return tmp.operator ->(); }
+	const_associative_reverse_iterator& operator ++() { associative_iterator_type::operator --(); return *this; }
+	const_associative_reverse_iterator operator ++(int) { const_associative_reverse_iterator old(*this); ++*this; return old; }
+	const_associative_reverse_iterator& operator --() { associative_iterator_type::operator ++(); return *this; }
+	const_associative_reverse_iterator operator --(int) { const_associative_reverse_iterator old(*this); --*this; return old; }
+
+	const tree_type* node() const { associative_iterator_type tmp(*this); --tmp; return tmp.node(); }
+	associative_iterator_type base() const { return associative_iterator_type(*this); }
+};
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::associative_reverse_iterator : public tcl::const_associative_reverse_iterator<stored_type, tree_type, container_type>
+{
+	typedef associative_iterator<stored_type, tree_type, container_type> associative_iterator_type;
+	typedef const_associative_iterator<stored_type, tree_type, container_type> const_associative_iterator_type;
+	typedef const_associative_reverse_iterator<stored_type, tree_type, container_type> base_reverse_iterator_type;
+public:
+	associative_reverse_iterator() : base_reverse_iterator_type() {}
+	explicit associative_reverse_iterator(const associative_iterator_type& _it) : const_associative_reverse_iterator<stored_type, tree_type, container_type>(_it) {}
+
+	stored_type& operator*() const {return const_cast<stored_type&>(base_reverse_iterator_type::operator*()); }
+	stored_type* operator->() const { return const_cast<stored_type*>(base_reverse_iterator_type::operator->()); }
+	associative_reverse_iterator& operator ++() { base_reverse_iterator_type::operator ++(); return *this; }
+	associative_reverse_iterator operator ++(int) { associative_reverse_iterator old(*this); ++*this; return old; }
+	associative_reverse_iterator& operator --() { base_reverse_iterator_type::operator --(); return *this; }
+	associative_reverse_iterator operator --(int) { associative_reverse_iterator old(*this); --*this; return old; }
+
+	tree_type* node() const { return const_cast<tree_type*>(base_reverse_iterator_type::node()); }
+	associative_iterator_type base() const { associative_iterator_type _it; _it.it = const_associative_iterator_type::it; _it.pParent = const_associative_iterator_type::pParent; return _it; }
+};
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_sequential_reverse_iterator : public tcl::const_sequential_iterator<stored_type, tree_type, container_type>
+{
+	typedef const_sequential_iterator<stored_type, tree_type, container_type> sequential_iterator_type;
+public:
+	const_sequential_reverse_iterator() : sequential_iterator_type() {}
+	explicit const_sequential_reverse_iterator(const sequential_iterator_type& _it) : sequential_iterator_type(_it) {}
+
+	const stored_type& operator*() const { sequential_iterator_type tmp(*this);  return (*--tmp); }
+	const stored_type* operator->() const { sequential_iterator_type tmp(*this); --tmp; return tmp.operator ->(); }
+	const_sequential_reverse_iterator& operator ++() { sequential_iterator_type::operator --(); return *this; }
+	const_sequential_reverse_iterator operator ++(int) { const_sequential_reverse_iterator old(*this); ++*this; return old; }
+	const_sequential_reverse_iterator& operator --() { sequential_iterator_type::operator ++(); return *this; }
+	const_sequential_reverse_iterator operator --(int) { const_sequential_reverse_iterator old(*this); --*this; return old; }
+
+	const tree_type* node() const { sequential_iterator_type tmp(*this); --tmp; return tmp.node(); }
+	sequential_iterator_type base() const { return sequential_iterator_type(*this); }
+};
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::sequential_reverse_iterator : public tcl::const_sequential_reverse_iterator<stored_type, tree_type, container_type>
+{
+	typedef sequential_iterator<stored_type, tree_type, container_type> sequential_iterator_type;
+	typedef const_sequential_iterator<stored_type, tree_type, container_type> const_sequential_iterator_type;
+	typedef const_sequential_reverse_iterator<stored_type, tree_type, container_type> base_reverse_iterator_type;
+public:
+	sequential_reverse_iterator() : base_reverse_iterator_type() {}
+	explicit sequential_reverse_iterator(const sequential_iterator_type& _it) : const_sequential_reverse_iterator<stored_type, tree_type, container_type>(_it) {}
+
+	stored_type& operator*() const { return const_cast<stored_type&>(base_reverse_iterator_type::operator*()); }
+	stored_type* operator->() const { return const_cast<stored_type*>(base_reverse_iterator_type::operator->()); }
+	sequential_reverse_iterator& operator ++() { base_reverse_iterator_type::operator ++(); return *this; }
+	sequential_reverse_iterator operator ++(int) { sequential_reverse_iterator old(*this); ++*this; return old; }
+	sequential_reverse_iterator& operator --() { base_reverse_iterator_type::operator --(); return *this; }
+	sequential_reverse_iterator operator --(int) { sequential_reverse_iterator old(*this); --*this; return old; }
+
+	tree_type* node() const { return const_cast<tree_type*>(base_reverse_iterator_type::node()); }
+	sequential_iterator_type base() const { sequential_iterator_type _it; _it.it = const_sequential_iterator_type::it; _it.pParent = const_sequential_iterator_type::pParent; return _it; }
+};
+

+ 119 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/reverse_node_iterator.h

@@ -0,0 +1,119 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "child_node_iterator.h"
+#include <iterator>
+
+namespace tcl 
+{
+	template<typename stored_type, typename tree_type, typename container_type> class associative_reverse_node_iterator;
+
+	template<typename T, typename U, typename V> class const_associative_reverse_node_iterator;
+	template<typename T, typename U, typename V> class associative_reverse_node_iterator;
+	template<typename T, typename U, typename V> class const_sequential_reverse_node_iterator;
+	template<typename T, typename U, typename V> class sequential_reverse_node_iterator;
+}
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_associative_reverse_node_iterator : public tcl::const_associative_node_iterator<stored_type, tree_type, container_type>
+{
+	typedef const_associative_node_iterator<stored_type, tree_type, container_type> associative_iterator_type;
+public:
+	const_associative_reverse_node_iterator() : associative_iterator_type() {}
+	explicit const_associative_reverse_node_iterator(const associative_iterator_type& _it) : associative_iterator_type(_it) {}
+	const_associative_reverse_node_iterator(associative_reverse_node_iterator<stored_type, tree_type, container_type>& _it) : associative_iterator_type(_it.it) {}
+
+	const tree_type& operator*() const { associative_iterator_type tmp(*this);  return (*--tmp); }
+	const tree_type* operator->() const { associative_iterator_type tmp(*this); --tmp; return tmp.operator ->(); }
+	const_associative_reverse_node_iterator& operator ++() { associative_iterator_type::operator --(); return *this; }
+	const_associative_reverse_node_iterator operator ++(int) { const_associative_reverse_node_iterator old(*this); ++*this; return old; }
+	const_associative_reverse_node_iterator& operator --() { associative_iterator_type::operator ++(); return *this; }
+	const_associative_reverse_node_iterator operator --(int) { const_associative_reverse_node_iterator old(*this); --*this; return old; }
+
+	associative_iterator_type base() const { return associative_iterator_type(*this); }
+};
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::associative_reverse_node_iterator : public tcl::const_associative_reverse_node_iterator<stored_type, tree_type, container_type>
+{
+	typedef associative_node_iterator<stored_type, tree_type, container_type> associative_iterator_type;
+	typedef const_associative_node_iterator<stored_type, tree_type, container_type> const_associative_iterator_type;
+	typedef const_associative_reverse_node_iterator<stored_type, tree_type, container_type> base_reverse_iterator_type;
+public:
+	associative_reverse_node_iterator() : base_reverse_iterator_type() {}
+	explicit associative_reverse_node_iterator(const associative_iterator_type& _it) : const_associative_reverse_node_iterator<stored_type, tree_type, container_type>(_it) {}
+
+	tree_type& operator*() const {return const_cast<tree_type&>(base_reverse_iterator_type::operator*()); }
+	tree_type* operator->() const { return const_cast<tree_type*>(base_reverse_iterator_type::operator->()); }
+	associative_reverse_node_iterator& operator ++() { base_reverse_iterator_type::operator ++(); return *this; }
+	associative_reverse_node_iterator operator ++(int) { associative_reverse_node_iterator old(*this); ++*this; return old; }
+	associative_reverse_node_iterator& operator --() { base_reverse_iterator_type::operator --(); return *this; }
+	associative_reverse_node_iterator operator --(int) { associative_reverse_node_iterator old(*this); --*this; return old; }
+
+	associative_iterator_type base() const { associative_iterator_type _it; _it.it = const_associative_iterator_type::it; _it.pParent = const_associative_iterator_type::pParent; return _it; }
+};
+
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::const_sequential_reverse_node_iterator : public tcl::const_sequential_node_iterator<stored_type, tree_type, container_type>
+{
+	typedef const_sequential_node_iterator<stored_type, tree_type, container_type> sequential_iterator_type;
+public:
+	const_sequential_reverse_node_iterator() : sequential_iterator_type() {}
+	explicit const_sequential_reverse_node_iterator(const sequential_iterator_type& _it) : sequential_iterator_type(_it) {}
+
+	const tree_type& operator*() const { sequential_iterator_type tmp(*this);  return (*--tmp); }
+	const tree_type* operator->() const { sequential_iterator_type tmp(*this); --tmp; return tmp.operator ->(); }
+	const_sequential_reverse_node_iterator& operator ++() { sequential_iterator_type::operator --(); return *this; }
+	const_sequential_reverse_node_iterator operator ++(int) { const_sequential_reverse_node_iterator old(*this); ++*this; return old; }
+	const_sequential_reverse_node_iterator& operator --() { sequential_iterator_type::operator ++(); return *this; }
+	const_sequential_reverse_node_iterator operator --(int) { const_sequential_reverse_node_iterator old(*this); --*this; return old; }
+
+	sequential_iterator_type base() const { return sequential_iterator_type(*this); }
+};
+
+template<typename stored_type, typename tree_type, typename container_type>
+class tcl::sequential_reverse_node_iterator : public tcl::const_sequential_reverse_node_iterator<stored_type, tree_type, container_type>
+{
+	typedef sequential_node_iterator<stored_type, tree_type, container_type> sequential_iterator_type;
+	typedef const_sequential_node_iterator<stored_type, tree_type, container_type> const_sequential_iterator_type;
+	typedef const_sequential_reverse_node_iterator<stored_type, tree_type, container_type> base_reverse_iterator_type;
+public:
+	sequential_reverse_node_iterator() : base_reverse_iterator_type() {}
+	explicit sequential_reverse_node_iterator(const sequential_iterator_type& _it) : const_sequential_reverse_node_iterator<stored_type, tree_type, container_type>(_it) {}
+
+	tree_type& operator*() const { return const_cast<tree_type&>(base_reverse_iterator_type::operator*()); }
+	tree_type* operator->() const { return const_cast<tree_type*>(base_reverse_iterator_type::operator->()); }
+	sequential_reverse_node_iterator& operator ++() { base_reverse_iterator_type::operator ++(); return *this; }
+	sequential_reverse_node_iterator operator ++(int) { sequential_reverse_node_iterator old(*this); ++*this; return old; }
+	sequential_reverse_node_iterator& operator --() { base_reverse_iterator_type::operator --(); return *this; }
+	sequential_reverse_node_iterator operator --(int) { sequential_reverse_node_iterator old(*this); --*this; return old; }
+
+	sequential_iterator_type base() const { sequential_iterator_type _it; _it.it = const_sequential_iterator_type::it; _it.pParent = const_sequential_iterator_type::pParent; return _it; }
+};
+

+ 283 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/sequential_tree.h

@@ -0,0 +1,283 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "basic_tree.h"
+#include "child_iterator.h"
+#include "child_node_iterator.h"
+#include "descendant_iterator.h"
+#include "descendant_node_iterator.h"
+#include "reverse_iterator.h"
+#include "reverse_node_iterator.h"
+#include <vector>
+#include <algorithm>
+#include <stdexcept>
+
+namespace tcl 
+{
+	template<typename T> class sequential_tree;
+
+	// overloaded comparison operations
+	template<typename T> bool operator == (const sequential_tree<T>& lhs, const sequential_tree<T>& rhs);
+	template<typename T> bool operator <  (const sequential_tree<T>& lhs, const sequential_tree<T>& rhs);
+	template<typename T> bool operator != (const sequential_tree<T>& lhs, const sequential_tree<T>& rhs) { return !(lhs == rhs); }
+	template<typename T> bool operator >  (const sequential_tree<T>& lhs, const sequential_tree<T>& rhs) { return rhs < lhs; }
+	template<typename T> bool operator <= (const sequential_tree<T>& lhs, const sequential_tree<T>& rhs) { return !(rhs < lhs); }
+	template<typename T> bool operator >= (const sequential_tree<T>& lhs, const sequential_tree<T>& rhs) { return !(lhs < rhs); }
+}
+
+template<typename stored_type>
+class tcl::sequential_tree : public tcl::basic_tree<stored_type, sequential_tree<stored_type>, std::vector<sequential_tree<stored_type>* > >
+{
+public:
+	// typedefs
+	typedef sequential_tree<stored_type> tree_type;
+	typedef std::vector<tree_type*> container_type;
+	typedef basic_tree<stored_type, tree_type, container_type > basic_tree_type;
+	typedef typename basic_tree_type::size_type basic_size_type;
+	using basic_tree_type::size_type;
+
+	// element iterator typedefs
+	typedef const_sequential_iterator<stored_type, tree_type, container_type>															const_iterator;
+	typedef sequential_iterator<stored_type, tree_type, container_type>																		iterator;
+	typedef const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>				const_pre_order_iterator;
+	typedef pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>							pre_order_iterator;
+	typedef const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>				const_post_order_iterator;
+	typedef post_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>							post_order_iterator;
+	typedef const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>			const_level_order_iterator;
+	typedef level_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>						level_order_iterator;
+	typedef sequential_reverse_iterator<stored_type, tree_type, container_type>														reverse_iterator;
+	typedef const_sequential_reverse_iterator<stored_type, tree_type, container_type>											const_reverse_iterator;
+
+	// node iterator typedefs
+	typedef const_sequential_node_iterator<stored_type, tree_type, container_type>												const_node_iterator;
+	typedef sequential_node_iterator<stored_type, tree_type, container_type>															node_iterator;
+	typedef const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>		const_pre_order_node_iterator;
+	typedef pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>					pre_order_node_iterator;
+	typedef const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>	const_post_order_node_iterator;
+	typedef post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>				post_order_node_iterator;
+	typedef const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type> const_level_order_node_iterator;
+	typedef level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>				level_order_node_iterator;
+	typedef sequential_reverse_node_iterator<stored_type, tree_type, container_type>											reverse_node_iterator;
+	typedef const_sequential_reverse_node_iterator<stored_type, tree_type, container_type>								const_reverse_node_iterator;
+
+	// constructors/destructor
+	explicit sequential_tree(const stored_type& value = stored_type()) : basic_tree_type(value) {}
+	explicit sequential_tree(typename basic_tree_type::size_type sz, const stored_type& value = stored_type()) : basic_tree_type(stored_type()) { insert(end(), sz, value); }
+	sequential_tree(const tree_type& rhs);  // copy constructor
+	template<typename iterator_type> sequential_tree(iterator_type it_beg, iterator_type it_end, const stored_type& value = stored_type()) : basic_tree_type(value) { while (it_beg != it_end) { insert(*it_beg); ++it_beg; } }
+	~sequential_tree() {clear(); }
+
+	// assignment operator
+	tree_type& operator = (const tree_type& rhs);
+
+	// child element iterator accessors
+	const_iterator begin() const { return const_iterator(basic_tree_type::children.begin(), this); }
+	const_iterator end() const { return const_iterator(basic_tree_type::children.end(), this); }
+	iterator begin() { return iterator(basic_tree_type::children.begin(), this); }
+	iterator end() { return iterator(basic_tree_type::children.end(), this); }
+
+	// child node iterator accessors
+	const_node_iterator node_begin() const { return const_node_iterator(basic_tree_type::children.begin(), this); }
+	const_node_iterator node_end() const { return const_node_iterator(basic_tree_type::children.end(), this); }
+	node_iterator node_begin() { return node_iterator(basic_tree_type::children.begin(), this); }
+	node_iterator node_end() { return node_iterator(basic_tree_type::children.end(), this); }
+	
+
+	// child element reverse iterator accessors
+	const_reverse_iterator rbegin() const {return const_reverse_iterator(end()); }
+	const_reverse_iterator rend() const {return const_reverse_iterator(begin()); }
+	reverse_iterator rbegin() {return reverse_iterator(end()); }
+	reverse_iterator rend() { return reverse_iterator(begin()); }
+
+	// descendant element iterator accessors
+	pre_order_iterator pre_order_begin() { return pre_order_iterator(this, true); }
+	pre_order_iterator pre_order_end() { return pre_order_iterator(this, false); }
+	const_pre_order_iterator pre_order_begin() const { return const_pre_order_iterator(this, true); }
+	const_pre_order_iterator pre_order_end() const { return const_pre_order_iterator(this, false); }
+	post_order_iterator post_order_begin() { return post_order_iterator(this, true); }
+	post_order_iterator post_order_end() { return post_order_iterator(this, false); }
+	const_post_order_iterator post_order_begin() const { return const_post_order_iterator(this, true); }
+	const_post_order_iterator post_order_end() const { return const_post_order_iterator(this, false); }
+	level_order_iterator level_order_begin() { return level_order_iterator(this, true); }
+	level_order_iterator level_order_end() { return level_order_iterator(this, false); }
+	const_level_order_iterator level_order_begin() const { return const_level_order_iterator(this, true); }
+	const_level_order_iterator level_order_end() const { return const_level_order_iterator(this, false); }
+
+	// child node reverse iterator accessors
+	const_reverse_node_iterator node_rbegin() const {return const_reverse_node_iterator(node_end()); }
+	const_reverse_node_iterator node_rend() const {return const_reverse_node_iterator(node_begin()); }
+	reverse_node_iterator node_rbegin() {return reverse_node_iterator(node_end()); }
+	reverse_node_iterator node_rend() { return reverse_node_iterator(node_begin()); }
+
+	// descendant node iterator accessors
+	pre_order_node_iterator pre_order_node_begin() { return pre_order_node_iterator(this, true); }
+	pre_order_node_iterator pre_order_node_end() { return pre_order_node_iterator(this, false); }
+	const_pre_order_node_iterator pre_order_node_begin() const { return const_pre_order_node_iterator(this, true); }
+	const_pre_order_node_iterator pre_order_node_end() const { return const_pre_order_node_iterator(this, false); }
+	post_order_node_iterator post_order_node_begin() { return post_order_node_iterator(this, true); }
+	post_order_node_iterator post_order_node_end() { return post_order_node_iterator(this, false); }
+	const_post_order_node_iterator post_order_node_begin() const { return const_post_order_node_iterator(this, true); }
+	const_post_order_node_iterator post_order_node_end() const { return const_post_order_node_iterator(this, false); }
+	level_order_node_iterator level_order_node_begin() { return level_order_node_iterator(this, true); }
+	level_order_node_iterator level_order_node_end() { return level_order_node_iterator(this, false); }
+	const_level_order_node_iterator level_order_node_begin() const { return const_level_order_node_iterator(this, true); }
+	const_level_order_node_iterator level_order_node_end() const { return const_level_order_node_iterator(this, false); }
+	
+
+	// public interface
+	typename basic_tree_type::size_type capacity() const { return basic_tree_type::children.capacity(); }
+	void reserve(typename basic_tree_type::size_type sz) { basic_tree_type::children.reserve(sz); }
+	tree_type& front() { return *basic_tree_type::children.front(); }
+	tree_type& back() { return *basic_tree_type::children.back(); }
+	const tree_type& front() const { return *basic_tree_type::children.front(); }
+	const tree_type& back() const { return *basic_tree_type::children.back(); }
+	void push_back(const stored_type& value);
+	void pop_back() { iterator it = end(); erase(--it); }
+
+	iterator insert(const stored_type& value);
+	iterator insert(const tree_type& tree_obj );
+	iterator insert(const_iterator pos, const stored_type& value);
+	iterator insert(const const_iterator& pos, const tree_type& tree_obj);
+	void insert(const_iterator pos, typename basic_tree_type::size_type num, const stored_type& value);
+	#if !defined(_MSC_VER) || _MSC_VER >= 1300 // insert range not available for VC6
+	template<typename iterator_type> void insert(const_iterator pos, iterator_type it_beg, iterator_type it_end) 
+	{ while (it_beg != it_end) { pos = insert(pos, *it_beg++); ++pos; } }
+	#endif
+	void set(const stored_type& value) { basic_tree_type::set(value); }
+	void set(const tree_type& tree_obj);
+	void swap(tree_type& rhs);
+	iterator erase(iterator it);
+	iterator erase(iterator beg_it, iterator end_it);
+	void clear();
+
+	// subscript operators
+	tree_type& operator [](basic_size_type index);
+	const tree_type& operator [](basic_size_type index) const; 
+
+	// children sort operations
+	template<typename T> void sort(const T& comparer) { std::sort(basic_tree_type::children.begin(), basic_tree_type::children.end(), sort_functor_deref<T>(comparer)); }
+	void sort() { std::sort(basic_tree_type::children.begin(), basic_tree_type::children.end(), sort_deref()); }
+
+	// descendant sort operations
+	template<typename T> void sort_descendants(const T& comparer)
+	{
+		post_order_iterator it = post_order_begin(), it_end = post_order_end();
+		for ( ; it != it_end; ++it )
+		{
+			it.node()->sort(comparer);
+		}
+	}
+	void sort_descendants(); 
+
+	// overloaded iterator arithmetic operators
+	friend const_iterator operator +(const const_iterator& lhs, typename basic_tree_type::size_type n) 
+	{ const_iterator temp(lhs); temp += n; return temp; }
+
+	friend const_iterator operator +(typename basic_tree_type::size_type n, const const_iterator& rhs)
+	{ const_iterator temp(rhs); temp += n; return temp; }
+
+	friend const_iterator operator -(const const_iterator& lhs, typename basic_tree_type::size_type n)
+	{ const_iterator temp(lhs); temp -= n; return temp; }
+
+	friend iterator operator +(const iterator& lhs, typename basic_tree_type::size_type n)
+	{ iterator temp(lhs); temp += n; return temp; }
+
+	friend iterator operator +(typename basic_tree_type::size_type n, const iterator& rhs)
+	{ iterator temp(rhs); temp += n; return temp; }
+
+	friend iterator operator -(const iterator& lhs, typename basic_tree_type::size_type n)
+	{ iterator temp(lhs); temp -= n; return temp; }
+
+	// overloaded node iterator arithmetic operators
+	friend const_node_iterator operator +(const const_node_iterator& lhs, typename basic_tree_type::size_type n) 
+	{ const_node_iterator temp(lhs); temp += n; return temp; }
+
+	friend const_node_iterator operator +(typename basic_tree_type::size_type n, const const_node_iterator& rhs)
+	{ const_node_iterator temp(rhs); temp += n; return temp; }
+
+	friend const_node_iterator operator -(const const_node_iterator& lhs, typename basic_tree_type::size_type n)
+	{ const_node_iterator temp(lhs); temp -= n; return temp; }
+
+	friend node_iterator operator +(const node_iterator& lhs, typename basic_tree_type::size_type n)
+	{ node_iterator temp(lhs); temp += n; return temp; }
+
+	friend node_iterator operator +(typename basic_tree_type::size_type n, const node_iterator& rhs)
+	{ node_iterator temp(rhs); temp += n; return temp; }
+
+	friend node_iterator operator -(const node_iterator& lhs, typename basic_tree_type::size_type n)
+	{ node_iterator temp(lhs); temp -= n; return temp; }
+
+
+private:
+	// sort() dereference functor
+	struct sort_deref
+	{
+		bool operator() (const tree_type* lhs, const tree_type* rhs)
+		{
+			return *lhs->get() < *rhs->get();
+		}
+	};
+
+	// sort<T>() dereference functor
+	template<typename T>
+	struct sort_functor_deref 
+	{
+		explicit sort_functor_deref(const T& sort_functor_) : sort_functor(sort_functor_) {}
+		bool operator() (const tree_type* lhs, const tree_type* rhs) const
+		{
+			return sort_functor(*lhs->get(), *rhs->get());
+		}
+		sort_functor_deref& operator = (const sort_functor_deref& rhs) { sort_functor = rhs->sort_functor; return *this; }
+		const T& sort_functor;
+	};
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class const_pre_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>;
+		friend class const_post_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>;
+		friend class const_level_order_descendant_iterator<stored_type, tree_type, container_type, tree_type>;
+		friend class const_pre_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>;
+		friend class const_post_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>;
+		friend class const_level_order_descendant_node_iterator<stored_type, tree_type, container_type, tree_type>;
+		friend bool operator == (const tree_type& lhs, const tree_type& rhs);
+		friend bool operator <  (const tree_type& lhs, const tree_type& rhs);
+	#else
+		template<typename T, typename U, typename V, typename W> friend class const_pre_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_post_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_level_order_descendant_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_pre_order_descendant_node_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_post_order_descendant_node_iterator;
+		template<typename T, typename U, typename V, typename W> friend class const_level_order_descendant_node_iterator;
+		friend bool operator ==<> (const tree_type& lhs, const tree_type& rhs);
+		friend bool operator < <> (const tree_type& lhs, const tree_type& rhs);
+	#endif
+};
+
+
+
+
+#include "sequential_tree.inl"

+ 333 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/sequential_tree.inl

@@ -0,0 +1,333 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+
+// copy constructor
+template<typename stored_type>
+tcl::sequential_tree<stored_type>::sequential_tree(const tree_type& rhs) : basic_tree_type(rhs)
+{
+	const_iterator it = rhs.begin();
+	const const_iterator it_end = rhs.end();
+	for ( ; it != it_end; ++it ) // do a deep copy by inserting children (and descendants)
+	{
+		insert(*it.node());
+	}
+}
+
+// assignment operator
+template<typename stored_type>
+tcl::sequential_tree<stored_type>& tcl::sequential_tree<stored_type>::operator = (const tree_type& rhs)
+{
+	if ( this == &rhs ) // check for self assignment
+		return *this;
+
+	clear();
+	basic_tree_type::operator =(rhs); // call base class operation
+
+	const_iterator it = rhs.begin(), it_end = rhs.end();
+	for ( ; it != it_end; ++it ) // insert children and descendants
+	{
+		insert(*it.node());
+	}
+	return *this;
+}
+
+// swap
+template<typename stored_type>
+void tcl::sequential_tree<stored_type>::swap(tree_type& rhs)
+{
+	tree_type temp(*this);
+
+	clear();
+	*this = rhs;
+
+	rhs.clear();
+	rhs = temp;
+}
+
+// insert(const stored_type&)
+template< typename stored_type>
+typename tcl::sequential_tree<stored_type>::iterator 
+tcl::sequential_tree<stored_type>::insert( const stored_type& value)
+{
+	// create a new tree_type object to hold the node object
+	tree_type* pNew_node; 
+	basic_tree_type::allocate_tree_type(pNew_node, tree_type(value));
+	pNew_node->set_parent(this);
+
+	const typename basic_tree_type::size_type sz = basic_tree_type::children.size();
+
+	// insert the tree node into the children container
+	const typename container_type::iterator it = basic_tree_type::children.insert(basic_tree_type::children.end(), pNew_node);
+
+	if ( sz == basic_tree_type::children.size() ) { // check for successful insertion
+		basic_tree_type::deallocate_tree_type(pNew_node);  // not successful.  delete new node and return end()
+		return iterator(basic_tree_type::children.end(), this);
+	}
+
+	return iterator(it, this);
+}
+
+// insert(const tree_type&)
+template< typename stored_type>
+typename tcl::sequential_tree<stored_type>::iterator 
+tcl::sequential_tree<stored_type>::insert(const tree_type& tree_obj)
+{
+	// insert current node
+	const iterator base_it = insert(*tree_obj.get());
+
+	if ( base_it != end() ) {
+		const_iterator it = tree_obj.begin();
+		const const_iterator it_end = tree_obj.end();
+
+		// call this function recursively thru derived tree for children
+		for ( ; it != it_end; ++it )
+			base_it.node()->insert(*it.node());
+	}
+	return base_it;
+}
+
+// push_back(const stored_type&)
+template< typename stored_type>
+void tcl::sequential_tree<stored_type>::push_back(const stored_type& value)
+{
+	// create a new tree_type object to hold the node object
+	tree_type* pNew_node; 
+	basic_tree_type::allocate_tree_type(pNew_node, tree_type(value));
+	pNew_node->set_parent(this);
+
+	basic_tree_type::children.push_back(pNew_node);
+}
+
+// insert(const_iterator, const stored_type&)
+template<typename stored_type>
+typename tcl::sequential_tree<stored_type>::iterator 
+tcl::sequential_tree<stored_type>::insert(const_iterator pos, const stored_type& value)
+{
+	// create a new tree_type object to hold the node object
+	tree_type* pNew_node = 0; 
+	basic_tree_type::allocate_tree_type(pNew_node, tree_type(value));
+	pNew_node->set_parent(this);
+
+	const typename std::vector<stored_type>::size_type sz = basic_tree_type::children.size();
+
+	// calculate the insertion point
+	const const_iterator beg_it = begin();
+	typename container_type::iterator pos_it = basic_tree_type::children.begin(); 
+	for ( ; pos != beg_it; --pos, ++pos_it) ;
+	// insert the tree node into the children container
+	const typename container_type::iterator it = basic_tree_type::children.insert(pos_it, pNew_node);
+
+	if ( sz == basic_tree_type::children.size() ) { // check for successful insertion
+		basic_tree_type::deallocate_tree_type(pNew_node);  // not successful.  delete new node and return end()
+		iterator end_it(basic_tree_type::children.end(), this);
+		return end_it;
+	}
+
+	iterator node_it(it, this);
+	return node_it;
+}
+
+// insert(const_iterator, size_type, const stored_type&)
+template<typename stored_type>
+void 
+tcl::sequential_tree<stored_type>::insert(const_iterator pos, const typename basic_tree_type::size_type num, const stored_type& value)
+{
+	for (typename basic_tree_type::size_type i = 0; i < num; ++i) {
+		pos = insert(pos, value);
+		++pos;
+	}
+}
+
+// insert(const_iterator, const tree_type&)
+template<typename stored_type>
+typename tcl::sequential_tree<stored_type>::iterator 
+tcl::sequential_tree<stored_type>::insert(const const_iterator& pos, const tree_type& tree_obj)
+{
+	// insert current node
+	const iterator base_it = insert(pos, *tree_obj.get());
+
+	if ( base_it != end() ) {
+		const_iterator it = tree_obj.begin();
+		const const_iterator it_end = tree_obj.end();
+
+		// call this function recursively thru derived tree for children
+		for ( ; it != it_end; ++it )
+			base_it.node()->insert(*it.node());
+	}
+	return base_it;
+}
+
+
+// set(const tree_type&)
+template< typename stored_type >
+void tcl::sequential_tree<stored_type>::set(const sequential_tree<stored_type>& tree_obj)
+{
+	set(*tree_obj.get()); // set data for this node
+
+	const_iterator it = tree_obj.begin();
+	const const_iterator it_end = tree_obj.end();
+	for ( ; it != it_end; ++it ) { // and insert all descendants of passed tree
+		insert(*it.node());
+	}
+}
+
+// clear()
+template< typename stored_type >
+void tcl::sequential_tree<stored_type>::clear()
+{
+	iterator it = begin();
+	const iterator it_end = end();
+	for ( ; it != it_end; ++it )
+	{
+		basic_tree_type::deallocate_tree_type(it.node()); // delete all child nodes
+	}
+	basic_tree_type::children.clear();  // and remove them from set
+}
+
+// erase(iterator)
+template<typename stored_type>
+typename tcl::sequential_tree<stored_type>::iterator 
+tcl::sequential_tree<stored_type>::erase(iterator it)
+{
+	// check for node presence
+	if (it.pParent != this)
+		return end();
+
+	// clear children
+	it.node()->clear(); 
+	deallocate_tree_type(it.node());
+
+	const iterator beg_it = begin();
+	typename container_type::iterator pos_it = basic_tree_type::children.begin();
+	for ( ; it != beg_it; --it, ++pos_it) ;  // get child iterator position
+
+	return iterator(basic_tree_type::children.erase(pos_it), this);
+}
+
+// erase(iterator, iterator)
+template<typename stored_type>
+typename tcl::sequential_tree<stored_type>::iterator 
+tcl::sequential_tree<stored_type>::erase(iterator beg_it, iterator end_it) 
+{
+	int delete_count = 0;
+	for (; beg_it != end_it; --end_it)
+		++delete_count;
+
+	for (int i = 0; i < delete_count; ++i) {
+		beg_it = erase(beg_it);
+	}
+
+	return beg_it;
+}
+
+// operator [](size_type)
+template<typename stored_type>
+tcl::sequential_tree<stored_type>& tcl::sequential_tree<stored_type>::operator [](basic_size_type index) 
+{ 
+	if (index >= basic_tree_type::size())
+		throw std::out_of_range("sequential_tree index out of range");
+
+	return *(begin() + index).node();
+}
+
+// operator [](size_type) const
+template<typename stored_type>
+const tcl::sequential_tree<stored_type>& tcl::sequential_tree<stored_type>::operator [](basic_size_type index) const 
+{ 
+	if (index >= basic_tree_type::size())
+		throw std::out_of_range("sequential_tree index out of range");
+
+	return *(begin() + index).node();
+}
+
+
+// operator ==
+template<typename stored_type>
+bool tcl::operator == (const sequential_tree<stored_type>& lhs, const sequential_tree<stored_type>& rhs) 
+{
+	// check this node
+	if (!(*lhs.get() == *rhs.get()))
+		return false;
+
+	typename sequential_tree<stored_type>::const_iterator lhs_it = lhs.begin();
+	const typename sequential_tree<stored_type>::const_iterator lhs_end = lhs.end();
+	typename sequential_tree<stored_type>::const_iterator rhs_it = rhs.begin();
+	const typename sequential_tree<stored_type>::const_iterator rhs_end = rhs.end();
+
+	for ( ; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it ) {
+		if (!(*lhs_it.node() == *rhs_it.node())) {
+			return false;
+		}
+	}
+
+	if (lhs_it != lhs.end() || rhs_it != rhs.end())
+		return false;
+
+	return true;
+}
+
+
+// operator <
+template<typename stored_type>
+bool tcl::operator < (const sequential_tree<stored_type>& lhs, const sequential_tree<stored_type>& rhs) 
+{
+	// check this node
+	if (*lhs.get() < *rhs.get())
+		return true;
+
+	typename sequential_tree<stored_type>::const_iterator lhs_it = lhs.begin();
+	const typename sequential_tree<stored_type>::const_iterator lhs_end = lhs.end();
+	typename sequential_tree<stored_type>::const_iterator rhs_it = rhs.begin();
+	const typename sequential_tree<stored_type>::const_iterator rhs_end = rhs.end();
+
+	for ( ; lhs_it != lhs_end && rhs_it != rhs_end; ++lhs_it, ++rhs_it ) {
+		if (*lhs_it.node() < *rhs_it.node()) {
+			return true;
+		}
+	}
+
+	if (lhs.size() != rhs.size()) {
+		return lhs.size() < rhs.size();
+	}
+
+	return false;
+}
+
+// sort_descendants()
+template<typename stored_type>
+void tcl::sequential_tree<stored_type>::sort_descendants() 
+{
+	post_order_iterator it = post_order_begin();
+	const post_order_iterator it_end = post_order_end();
+	for ( ; it != it_end; ++it )
+	{
+		it.node()->sort();
+	}
+}
+
+
+

+ 135 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/tree.h

@@ -0,0 +1,135 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "associative_tree.h"
+#include <set>
+
+namespace tcl
+{
+// forward declaration for deref comparison functor
+template<typename stored_type, typename node_compare_type > class tree;
+
+	// deref comparison functor, derive from binary function per Scott Meyer
+	template<typename stored_type, typename node_compare_type >
+	struct tree_deref_less
+	{
+		bool operator () (const tree<stored_type, node_compare_type>* lhs, const tree<stored_type, node_compare_type>* rhs) const 
+		{
+			// call < on actual object
+			return node_compare_type()(*lhs->get(), *rhs->get());
+		}
+	};
+}
+
+
+
+
+// node object type.  forwards most operations to base_tree_type, 
+// instanciates base_tree_type with type of container (set of unique_tree ptrs) to use for node and key comparisons
+template<typename stored_type, typename node_compare_type = std::less<stored_type> >
+class tcl::tree : public tcl::associative_tree<stored_type, tcl::tree<stored_type, node_compare_type>,  std::set<tcl::tree<stored_type, node_compare_type>*, tcl::tree_deref_less<stored_type, node_compare_type> > >
+{
+public:
+	// typedefs
+	typedef tree<stored_type, node_compare_type> tree_type;
+	typedef tree_deref_less<stored_type, node_compare_type> key_compare;
+	typedef tree_deref_less<stored_type, node_compare_type> value_compare;
+	typedef std::set<tree_type*, key_compare> container_type;
+	typedef basic_tree<stored_type, tree_type,  container_type> basic_tree_type;
+	typedef associative_tree<stored_type, tree_type,  container_type> associative_tree_type;
+
+	// constructors/destructor
+	explicit tree( const stored_type& value = stored_type() ) : associative_tree_type(value) {}
+	template<typename iterator_type> tree(iterator_type it_beg, iterator_type it_end, const stored_type& value = stored_type()) : associative_tree_type(value) { while (it_beg != it_end) { insert(*it_beg); ++it_beg; } }
+	tree( const tree_type& rhs ); // copy constructor
+	~tree() { associative_tree_type::clear(); }
+
+	// assignment operator
+	tree_type& operator = (const tree_type& rhs);
+
+	// public interface
+public:
+	typename associative_tree_type::iterator insert(const stored_type& value) { return associative_tree_type::insert(value, this); }
+	typename associative_tree_type::iterator insert(const typename associative_tree_type::const_iterator pos, const stored_type& value) { return associative_tree_type::insert(pos, value, this); }
+	typename associative_tree_type::iterator insert(const tree_type& tree_obj ) { return associative_tree_type::insert(tree_obj, this); }
+	typename associative_tree_type::iterator insert(const typename associative_tree_type::const_iterator pos, const tree_type& tree_obj) { return associative_tree_type::insert(pos, tree_obj, this); }
+	#if !defined(_MSC_VER) || _MSC_VER >= 1300 // insert range not available for VC6
+	template<typename iterator_type> void insert(iterator_type it_beg, iterator_type it_end) { while ( it_beg != it_end ) insert(*it_beg++); }
+	#endif
+	void swap(tree_type& rhs);
+
+	// descendant element iterator accessors
+	typedef typename associative_tree_type::post_order_iterator post_order_iterator_type;
+	typedef typename associative_tree_type::const_post_order_iterator const_post_order_iterator_type;
+	typedef typename associative_tree_type::pre_order_iterator pre_order_iterator_type;
+	typedef typename associative_tree_type::const_pre_order_iterator const_pre_order_iterator_type;
+	typedef typename associative_tree_type::level_order_iterator level_order_iterator_type;
+	typedef typename associative_tree_type::const_level_order_iterator const_level_order_iterator_type;
+
+	pre_order_iterator_type pre_order_begin() { return pre_order_iterator_type(this, true); }
+	pre_order_iterator_type pre_order_end() { return pre_order_iterator_type(this, false); }
+	const_pre_order_iterator_type pre_order_begin() const { return const_pre_order_iterator_type(this, true); }
+	const_pre_order_iterator_type pre_order_end() const { return const_pre_order_iterator_type(this, false); }
+	post_order_iterator_type post_order_begin() { return post_order_iterator_type(this, true); }
+	post_order_iterator_type post_order_end() { return post_order_iterator_type(this, false); }
+	const_post_order_iterator_type post_order_begin() const { return const_post_order_iterator_type(this, true); }
+	const_post_order_iterator_type post_order_end() const { return const_post_order_iterator_type(this, false); }
+	level_order_iterator_type level_order_begin() { return level_order_iterator_type(this, true); }
+	level_order_iterator_type level_order_end() { return level_order_iterator_type(this, false); }
+	const_level_order_iterator_type level_order_begin() const { return const_level_order_iterator_type(this, true); }
+	const_level_order_iterator_type level_order_end() const { return const_level_order_iterator_type(this, false); }
+
+	// descendant node iterator accessors
+	typedef typename associative_tree_type::pre_order_node_iterator pre_order_node_iterator_type;
+	typedef typename associative_tree_type::const_pre_order_node_iterator const_pre_order_node_iterator_type;
+	typedef typename associative_tree_type::post_order_node_iterator post_order_node_iterator_type;
+	typedef typename associative_tree_type::const_post_order_node_iterator const_post_order_node_iterator_type;
+	typedef typename associative_tree_type::level_order_node_iterator level_order_node_iterator_type;
+	typedef typename associative_tree_type::const_level_order_node_iterator const_level_order_node_iterator_type;
+
+	pre_order_node_iterator_type pre_order_node_begin() { return pre_order_node_iterator_type(this, true); }
+	pre_order_node_iterator_type pre_order_node_end() { return pre_order_node_iterator_type(this, false); }
+	const_pre_order_node_iterator_type pre_order_node_begin() const { return const_pre_order_node_iterator_type(this, true); }
+	const_pre_order_node_iterator_type pre_order_node_end() const { return const_pre_order_node_iterator_type(this, false); }
+	post_order_node_iterator_type post_order_node_begin() { return post_order_node_iterator_type(this, true); }
+	post_order_node_iterator_type post_order_node_end() { return post_order_node_iterator_type(this, false); }
+	const_post_order_node_iterator_type post_order_node_begin() const { return const_post_order_node_iterator_type(this, true); }
+	const_post_order_node_iterator_type post_order_node_end() const { return const_post_order_node_iterator_type(this, false); }
+	level_order_node_iterator_type level_order_node_begin() { return level_order_node_iterator_type(this, true); }
+	level_order_node_iterator_type level_order_node_end() { return level_order_node_iterator_type(this, false); }
+	const_level_order_node_iterator_type level_order_node_begin() const { return const_level_order_node_iterator_type(this, true); }
+	const_level_order_node_iterator_type level_order_node_end() const { return const_level_order_node_iterator_type(this, false); }
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class basic_tree<stored_type, tree_type, container_type>;
+	#else
+		template<typename T, typename U, typename V> friend class basic_tree;
+	#endif
+};
+
+#include "tree.inl"

+ 76 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/tree.inl

@@ -0,0 +1,76 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+
+// copy constructor
+template<typename stored_type, typename node_compare_type>
+tcl::tree<stored_type, node_compare_type>::tree( const tree_type& rhs ) : associative_tree_type(rhs)
+{
+	typename associative_tree_type::const_iterator it = rhs.begin();
+	const typename associative_tree_type::const_iterator it_end = rhs.end();
+	for ( ; it != it_end; ++it ) // do a deep copy by inserting children (and descendants)
+	{
+		associative_tree_type::insert(*it.node(), this);
+	}
+}
+
+// assignment operator
+template<typename stored_type, typename node_compare_type>
+tcl::tree<stored_type, node_compare_type>& 
+tcl::tree<stored_type, node_compare_type>::operator = (const tree_type& rhs)
+{
+	if (!associative_tree_type::is_root()) // can assign only to root node
+		return *this;
+
+	if ( this == &rhs ) // check for self assignment
+		return *this;
+
+	associative_tree_type::clear();
+	basic_tree_type::operator =(rhs); // call base class operation
+
+	typename associative_tree_type::const_iterator it = rhs.begin();
+	const typename associative_tree_type::const_iterator it_end = rhs.end();
+	for ( ; it != it_end; ++it ) // insert children and descendants
+	{
+		associative_tree_type::insert(*it.node(), this);
+	}
+	return *this;
+}
+
+// swap
+template<typename stored_type, typename node_compare_type>
+void tcl::tree<stored_type, node_compare_type>::swap(tree_type& rhs)
+{
+	tree_type temp(*this);
+
+	associative_tree_type::clear();
+	*this = rhs;
+
+	rhs.clear();
+	rhs = temp;
+}
+
+

+ 183 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/unique_tree.h

@@ -0,0 +1,183 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#pragma once
+#include "associative_tree.h"
+#include "ordered_iterator.h"
+#include <set>
+
+namespace tcl
+{
+	// deref less for ordered children set
+	template<typename tree_type, typename node_order_compare_type>
+	struct deref_ordered_compare
+	{
+		bool operator() (const tree_type* lhs, const tree_type* rhs) const { return node_order_compare_type() (*lhs->get(), *rhs->get()); }
+	};
+
+	// forward declaration for deref comparison functor
+	template<typename stored_type, typename node_compare_type, typename node_order_compare_type >
+	class unique_tree;
+
+	// deref comparison functor, derive from binary function per Scott Meyer
+	template<typename stored_type, typename node_compare_type, typename node_order_compare_type >
+	struct unique_tree_deref_less : public std::binary_function<const unique_tree<stored_type, node_compare_type, node_order_compare_type>*, const unique_tree<stored_type, node_compare_type, node_order_compare_type>*, bool>
+	{
+		bool operator () (const unique_tree<stored_type, node_compare_type, node_order_compare_type>* lhs, const unique_tree<stored_type, node_compare_type, node_order_compare_type>* rhs) const
+		{
+			// call < on actual object
+			return node_compare_type()(*lhs->get(), *rhs->get());
+		}
+	};
+}
+
+
+
+
+// instanciates base_tree_type with type of container (set of unique_tree ptrs) to use for node and key comparisons
+template<typename stored_type, typename node_compare_type = std::less<stored_type>, typename node_order_compare_type = node_compare_type >
+class tcl::unique_tree : public tcl::associative_tree<stored_type, tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>,  std::set<tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>*, tcl::unique_tree_deref_less<stored_type, node_compare_type, node_order_compare_type> > >
+{
+public:
+	// typedefs
+	typedef unique_tree<stored_type, node_compare_type, node_order_compare_type> tree_type;
+	typedef unique_tree_deref_less<stored_type, node_compare_type, node_order_compare_type> key_compare;
+	typedef unique_tree_deref_less<stored_type, node_compare_type, node_order_compare_type> value_compare;
+	typedef std::set<tree_type*, key_compare> container_type;
+	typedef basic_tree<stored_type, tree_type, container_type> basic_tree_type;
+	typedef associative_tree<stored_type, tree_type, container_type> associative_tree_type;
+	typedef typename associative_tree_type::iterator associative_iterator_type;
+	typedef typename associative_tree_type::const_iterator associative_const_iterator_type;
+
+	typedef const_unique_tree_ordered_iterator<stored_type, node_compare_type, node_order_compare_type> const_ordered_iterator;
+	typedef unique_tree_ordered_iterator<stored_type, node_compare_type, node_order_compare_type> ordered_iterator;
+
+	// needed for inl function definitions in VC8
+	typedef typename associative_tree_type::iterator child_iterator;
+	typedef typename associative_tree_type::const_iterator const_child_iterator;
+
+	// constructors/destructor
+	explicit unique_tree( const stored_type& value = stored_type() ) : associative_tree_type(value), pOrphans(0), allowing_orphans(false) {}
+	unique_tree( const tree_type& rhs ); // copy constructor
+	template<typename iterator_type> unique_tree(iterator_type it_beg, iterator_type it_end, const stored_type& value = stored_type()) : associative_tree_type(value), pOrphans(0), allowing_orphans(false) { while (it_beg != it_end) { insert(*it_beg); ++it_beg; } }
+	~unique_tree() { clear(); if ( pOrphans ) basic_tree_type::deallocate_tree_type(pOrphans); }
+
+	// public interface
+public:
+	tree_type& operator = (const tree_type& rhs);  // assignment operator
+	typename associative_tree_type::iterator insert(const stored_type& value);
+	typename associative_tree_type::iterator insert(const typename associative_tree_type::const_iterator pos, const stored_type& value) { return associative_tree_type::insert(pos, value, this); }
+	typename associative_tree_type::iterator insert(const tree_type& tree_obj );
+	typename associative_tree_type::iterator insert(const typename associative_tree_type::const_iterator pos, const tree_type& tree_obj) { return associative_tree_type::insert(pos, tree_obj, this); }
+	void swap(tree_type& rhs);
+
+	typename associative_tree_type::iterator insert( const stored_type& parent_obj, const stored_type& value);
+	#if !defined(_MSC_VER) || _MSC_VER >= 1300 // insert range not available for VC6
+	template<typename iterator_type> void insert(iterator_type it_beg, iterator_type it_end) { while ( it_beg != it_end ) insert(*it_beg++); }
+	#endif
+	typename associative_tree_type::iterator find_deep(const stored_type& value);
+	typename associative_tree_type::const_iterator find_deep(const stored_type& value) const;
+
+	const_ordered_iterator ordered_begin() const { return const_ordered_iterator(ordered_children.begin()); }
+	const_ordered_iterator ordered_end() const { return const_ordered_iterator(ordered_children.end()); }
+	ordered_iterator ordered_begin() { return ordered_iterator(ordered_children.begin()); }
+	ordered_iterator ordered_end() { return ordered_iterator(ordered_children.end()); }
+	ordered_iterator find_ordered(const stored_type& value);
+	const_ordered_iterator find_ordered(const stored_type& value) const;
+	bool erase(const stored_type& value);
+	void erase(associative_iterator_type it);
+	void erase(associative_iterator_type it_beg, associative_iterator_type it_end);
+	void clear();
+	bool allow_orphans() const { return get_root()->allowing_orphans; }
+	void allow_orphans(const bool allow) const { get_root()->allowing_orphans = allow; }
+	const tree_type* get_orphans() const { return get_root()->pOrphans; }
+	bool is_orphan() const { const tree_type* const root = get_root(); return (!root->empty() && root->ordered_children.empty()); }
+
+	// descendant element iterator accessors
+	typedef typename associative_tree_type::post_order_iterator post_order_iterator_type;
+	typedef typename associative_tree_type::const_post_order_iterator const_post_order_iterator_type;
+	typedef typename associative_tree_type::pre_order_iterator pre_order_iterator_type;
+	typedef typename associative_tree_type::const_pre_order_iterator const_pre_order_iterator_type;
+	typedef typename associative_tree_type::level_order_iterator level_order_iterator_type;
+	typedef typename associative_tree_type::const_level_order_iterator const_level_order_iterator_type;
+
+	pre_order_iterator_type pre_order_begin() { return pre_order_iterator_type(this, true); }
+	pre_order_iterator_type pre_order_end() { return pre_order_iterator_type(this, false); }
+	const_pre_order_iterator_type pre_order_begin() const { return const_pre_order_iterator_type(this, true); }
+	const_pre_order_iterator_type pre_order_end() const { return const_pre_order_iterator_type(this, false); }
+	post_order_iterator_type post_order_begin() { return post_order_iterator_type(this, true); }
+	post_order_iterator_type post_order_end() { return post_order_iterator_type(this, false); }
+	const_post_order_iterator_type post_order_begin() const { return const_post_order_iterator_type(this, true); }
+	const_post_order_iterator_type post_order_end() const { return const_post_order_iterator_type(this, false); }
+	level_order_iterator_type level_order_begin() { return level_order_iterator_type(this, true); }
+	level_order_iterator_type level_order_end() { return level_order_iterator_type(this, false); }
+	const_level_order_iterator_type level_order_begin() const { return const_level_order_iterator_type(this, true); }
+	const_level_order_iterator_type level_order_end() const { return const_level_order_iterator_type(this, false); }
+
+	// descendant node iterator accessors
+	typedef typename associative_tree_type::pre_order_node_iterator pre_order_node_iterator_type;
+	typedef typename associative_tree_type::const_pre_order_node_iterator const_pre_order_node_iterator_type;
+	typedef typename associative_tree_type::post_order_node_iterator post_order_node_iterator_type;
+	typedef typename associative_tree_type::const_post_order_node_iterator const_post_order_node_iterator_type;
+	typedef typename associative_tree_type::level_order_node_iterator level_order_node_iterator_type;
+	typedef typename associative_tree_type::const_level_order_node_iterator const_level_order_node_iterator_type;
+
+	pre_order_node_iterator_type pre_order_node_begin() { return pre_order_node_iterator_type(this, true); }
+	pre_order_node_iterator_type pre_order_node_end() { return pre_order_node_iterator_type(this, false); }
+	const_pre_order_node_iterator_type pre_order_node_begin() const { return const_pre_order_node_iterator_type(this, true); }
+	const_pre_order_node_iterator_type pre_order_node_end() const { return const_pre_order_node_iterator_type(this, false); }
+	post_order_node_iterator_type post_order_node_begin() { return post_order_node_iterator_type(this, true); }
+	post_order_node_iterator_type post_order_node_end() { return post_order_node_iterator_type(this, false); }
+	const_post_order_node_iterator_type post_order_node_begin() const { return const_post_order_node_iterator_type(this, true); }
+	const_post_order_node_iterator_type post_order_node_end() const { return const_post_order_node_iterator_type(this, false); }
+	level_order_node_iterator_type level_order_node_begin() { return level_order_node_iterator_type(this, true); }
+	level_order_node_iterator_type level_order_node_end() { return level_order_node_iterator_type(this, false); }
+	const_level_order_node_iterator_type level_order_node_begin() const { return const_level_order_node_iterator_type(this, true); }
+	const_level_order_node_iterator_type level_order_node_end() const { return const_level_order_node_iterator_type(this, false); }
+
+private:
+	void set(const stored_type& value) { basic_tree_type::set(value); }
+	void set(const tree_type& tree_obj);
+	void inform_grandparents( tree_type* pNew_child, tree_type* pParent );
+	bool check_for_duplicate(const stored_type& value, const tree_type* pParent) const;
+	const tree_type* get_root() const;
+
+private:
+	// data
+	mutable std::set<tree_type*, key_compare > descendents;
+	std::multiset<tree_type*, deref_ordered_compare<tree_type, node_order_compare_type> > ordered_children;
+	mutable tree_type* pOrphans;
+	mutable bool allowing_orphans;
+
+	// friends
+	#if defined(_MSC_VER) && _MSC_VER < 1300
+		friend class basic_tree<stored_type, tree_type, container_type>;
+	#else
+		template<typename T, typename U, typename V> friend class basic_tree;
+	#endif
+};
+
+#include "unique_tree.inl"

+ 445 - 0
comx_sdk.node/include/ModelIO.buffer/tcl_5.0.6/unique_tree.inl

@@ -0,0 +1,445 @@
+/*******************************************************************************
+Tree Container Library: Generic container library to store data in tree-like structures.
+Copyright (c) 2006  Mitchel Haas
+
+This software is provided 'as-is', without any express or implied warranty. 
+In no event will the author be held liable for any damages arising from 
+the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1.	The origin of this software must not be misrepresented; 
+you must not claim that you wrote the original software. 
+If you use this software in a product, an acknowledgment in the product 
+documentation would be appreciated but is not required.
+
+2.	Altered source versions must be plainly marked as such, 
+and must not be misrepresented as being the original software.
+
+3.	The above copyright notice and this permission notice may not be removed 
+or altered from any source distribution.
+
+For complete documentation on this library, see http://www.datasoftsolutions.net
+Email questions, comments or suggestions to mhaas@datasoftsolutions.net
+*******************************************************************************/
+#include <algorithm>
+
+// copy constructor
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::unique_tree( const tree_type& rhs ) 
+	: associative_tree_type(rhs), pOrphans(0), allowing_orphans(false)
+{
+	allowing_orphans = rhs.allowing_orphans;  // copy orphan flag
+
+	if (rhs.pOrphans) { // orphans present?
+		basic_tree_type::allocate_tree_type(pOrphans, tree_type());
+		associative_const_iterator_type it = rhs.pOrphans->begin();
+		const associative_const_iterator_type it_end = rhs.pOrphans->end();
+		for ( ; it != it_end; ++it ) { // copy orphans
+			pOrphans->insert(*it.node());
+		}
+	} else 
+		pOrphans = 0;
+
+	associative_const_iterator_type it = rhs.begin();
+	const associative_const_iterator_type it_end = rhs.end();
+	for ( ; it != it_end; ++it ) { // do deep copy by inserting children (and descendants)
+		insert(*it.node());
+	}
+}
+
+// assignment operator
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>& 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::operator = (const tree_type& rhs)
+{
+	if (!associative_tree_type::is_root()) // can assign only to root node
+		return *this;
+
+	if ( this == &rhs )  // check for self assignment
+		return *this;
+
+	clear();
+	basic_tree_type::operator =(rhs); // base class operation
+
+	allowing_orphans = rhs.allowing_orphans;
+
+	if (rhs.pOrphans) { // orphans present?
+		basic_tree_type::allocate_tree_type(pOrphans, tree_type());  // yes.  copy them
+		associative_const_iterator_type it = rhs.pOrphans->begin();
+		const associative_const_iterator_type it_end = rhs.pOrphans->end();
+		for ( ; it != it_end; ++it ) {
+			pOrphans->insert(*it.node());
+		}
+	} else 
+		pOrphans = 0;
+
+	associative_const_iterator_type it = rhs.begin();
+	const associative_const_iterator_type it_end = rhs.end();
+	for ( ; it != it_end; ++it ) {  // copy all children (and descendants)
+		insert(*it.node());
+	}
+
+	return *this;
+}
+
+
+// set(const tree_type&)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+void tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::set(const tree_type& tree_obj)
+{
+	if ( !check_for_duplicate(*tree_obj.get(), this)) { // duplicate node exist in tree?
+		// no.  OK to set this node
+		basic_tree_type::set(*tree_obj.get());
+
+		associative_const_iterator_type it = tree_obj.begin(), it_end = tree_obj.end();
+		for ( ; it != it_end; ++it ) { // insert any children
+			insert(*it.node());
+		}
+
+		if ( tree_obj.pOrphans && allow_orphans() ) { // copy orphans if any present
+			get_root()->pOrphans->set(*tree_obj.pOrphans );
+		}  
+
+	}
+}
+
+
+// insert(const stored_type&)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+typename tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::child_iterator 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::insert(const stored_type& value) 
+{ 
+	const tree_type* const pRoot = get_root();
+	if ( allow_orphans() && pRoot->pOrphans ) { // orphans present?
+		// yes.  check orphans for child
+		const associative_iterator_type oit = pRoot->pOrphans->find_deep(value);
+		if ( oit != pRoot->pOrphans->end() ) { 
+			// child is an orphan.  update orphan with new data
+			oit.node()->set(stored_type(value));
+			tree_type orphan;
+			orphan.set(*oit.node());
+			pRoot->pOrphans->erase(*oit);
+			return insert(orphan);
+		} 
+	} 
+	
+	// stored obj doesn't already exist in an orphan
+	if ( !check_for_duplicate(value, this)) { // check for duplication
+		const associative_iterator_type it = associative_tree_type::insert(value, this);
+		ordered_children.insert(it.node());  // no duplicate exists.  insert new node
+		inform_grandparents(it.node(), this );
+		return it;
+	} else
+		return associative_tree_type::end(); // duplicate node exists.  don't insert
+
+}
+
+// insert(const tree_type&)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+typename tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::child_iterator 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::insert(const tree_type& tree_obj )
+{
+	if ( tree_obj.pOrphans && allow_orphans() ) { // have orphans?
+		get_root()->pOrphans->insert(*tree_obj.pOrphans ); // yes.  copy orphans
+	}  
+
+	// insert current node
+	associative_iterator_type base_it = insert(*tree_obj.get());
+
+	if ( base_it == associative_tree_type::end() ) { // insert successful?
+		// no.  but, the node may have existed here previously.  check if so
+		base_it = associative_tree_type::find(*tree_obj.get()); 
+	}
+
+	if ( base_it != associative_tree_type::end() ) {  // node exist?
+		associative_const_iterator_type it = tree_obj.begin();
+		const associative_const_iterator_type it_end = tree_obj.end();
+
+		// call this function recursively to insert children and descendants
+		for ( ; it != it_end; ++it )
+			base_it.node()->insert(*it.node());
+	}
+	return base_it;
+}
+
+// insert(const stored_type&, const stored_type&)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+typename tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::child_iterator 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::insert( const stored_type& parent_obj, const stored_type& value)
+{
+	if ( !(parent_obj < (*basic_tree_type::get())) && !((*basic_tree_type::get()) < parent_obj) ) { // is this node the parent?	
+		return insert(value);  // yes.  insert the node here.
+	}
+
+	// find parent node
+	associative_iterator_type it;
+	const associative_iterator_type it_parent = find_deep(parent_obj);
+
+	const tree_type* const pRoot = get_root();
+	if ( it_parent != associative_tree_type::end() ) {
+		// found parent node, 
+		if ( allow_orphans() && pRoot->pOrphans ) {
+			// orphans present.  check orphans for child
+			const associative_iterator_type oit = pRoot->pOrphans->find_deep(value);
+			if ( oit != pRoot->pOrphans->end() ) {
+				// child is an orphan.  update orphan with new data
+				oit.node()->set(stored_type(value));
+				tree_type orphan;
+				orphan.set(*oit.node());
+				pRoot->pOrphans->erase(*oit);
+				it = it_parent.node()->insert(orphan);
+			} else
+				it = it_parent.node()->insert(value); // child not an orphan. inset child node in parent 
+		} else {
+			it = it_parent.node()->insert(value); // no orphans.  insert child node in parent
+		}
+		if ( it == it_parent.node()->end() ) // was node inserted successfully?
+			return associative_tree_type::end(); // no.  return proper end()
+	} else if (allow_orphans() ) { 
+		// parent not found.  do we have orphans?
+		if ( !pRoot->pOrphans ) {
+			basic_tree_type::allocate_tree_type(pRoot->pOrphans, tree_type());  // no, instanciate them
+		}
+
+		associative_iterator_type oit = pRoot->pOrphans->find_deep(parent_obj);
+
+		// orphans contain parent?
+		if ( oit == pRoot->pOrphans->end() ) {
+			// no.  create parent in orphans
+			oit = pRoot->pOrphans->insert(parent_obj);
+			pRoot->pOrphans->ordered_children.clear();  // orphans need no ordered children
+		} 
+
+		const associative_iterator_type child_oit = pRoot->pOrphans->find_deep(value);
+		if ( child_oit != pRoot->pOrphans->end() ) {
+			// child is an orphan.  update orphan with new data
+			child_oit.node()->set(stored_type(value));
+			tree_type orphan;
+			orphan.set(*child_oit.node());
+			pRoot->pOrphans->erase(*child_oit);
+			it = oit.node()->insert(orphan);
+			oit.node()->ordered_children.clear();
+		} else {
+			it = oit.node()->insert(value); // child not an orphan.  insert child in parent orphan
+			oit.node()->ordered_children.clear();
+		}
+
+		if ( it == oit.node()->end() ) // was child inserted as orphan?
+			return associative_tree_type::end();  // no.  return proper end()
+	} else {
+		return associative_tree_type::end(); // couldn't find parent, and orphans not allowed
+	}
+
+	return it;
+}
+
+
+// find_deep(const stored_type&)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+typename tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::child_iterator 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::find_deep(const stored_type& value) 
+{
+	tree_type tree_node(value);  // create seach node
+	const typename std::set<tree_type*, key_compare>::iterator desc_it = descendents.find(&tree_node);
+	if (desc_it == descendents.end()) // node found in descendants?
+		return associative_tree_type::end();  // no.  node not a descendant of this node
+
+	// node is some type of descendant.  check if it's an immediate child
+	associative_iterator_type it = associative_tree_type::find(value);
+	if ( it != associative_tree_type::end() )
+		return it;
+
+	// node not an immediate child.  
+	it = associative_tree_type::begin();
+	const associative_iterator_type it_end = associative_tree_type::end();
+	for ( ; it != it_end; ++it ) {  // iterate over children and call this fcn recursively
+		const associative_iterator_type grandchild_it = it.node()->find_deep(value);
+		if ( grandchild_it != it.node()->end() ) 
+			return grandchild_it;  // found it
+	}
+
+	return associative_tree_type::end();
+}
+
+// find_deep(const stored_type&) const
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+typename tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::const_child_iterator 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::find_deep(const stored_type& value) const
+{
+	associative_const_iterator_type it_end = associative_tree_type::end();
+	tree_type tree_node(value);  // create seach node
+	typename std::set<tree_type*, key_compare>::const_iterator desc_it = descendents.find(&tree_node);
+	if (desc_it == descendents.end())  // node found in descendants?
+		return it_end;  // no.  node not a descendant of this node
+
+	// node is some type of descendant.  check if it's an immediate child
+	associative_const_iterator_type it = associative_tree_type::find(value);
+	if ( it != it_end )
+		return it;
+
+	// node not an immediate child.  
+	it = associative_tree_type::begin();
+	for ( ; it != it_end; ++it ) { // iterate over children and call this fcn recursively
+		associative_const_iterator_type grandchild_it = it.node()->find_deep(value);
+		associative_const_iterator_type grandchild_it_end = it.node()->end();
+		if ( grandchild_it != grandchild_it_end )
+			return grandchild_it;  // found it
+	}
+
+	return it_end;
+}
+
+
+// clear()
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+void tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::clear()
+{
+	// create descendant remove set
+	std::set<tree_type*, key_compare> remove_set;
+	remove_set.swap(descendents);  // get a copy of the descendants, and clear them
+
+	tree_type* pParent = basic_tree_type::parent();
+	while ( pParent != 0 ) {  // climb up to the root node
+		std::set<tree_type*, key_compare> dest_set;  // create a difference set
+		std::set_difference( pParent->descendents.begin(), pParent->descendents.end(),
+			remove_set.begin(), remove_set.end(), std::inserter(dest_set, dest_set.begin()), key_compare() );
+		pParent->descendents.swap(dest_set);  // and remove the deleted descendants
+		pParent = pParent->parent();
+	}
+
+	associative_tree_type::clear(); // call base class operation
+	ordered_children.clear();
+	descendents.clear();
+
+	if ( pOrphans ) { // if this is the root, clear orphans also
+		pOrphans->clear();
+	}
+}
+
+
+// inform_grandparents(tree_type*, tree_type*)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+void tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::inform_grandparents( tree_type* new_child, tree_type* pParent  )
+{
+	if ( pParent) {  // traverse to root, adding new child to descendants to every node
+		pParent->descendents.insert(new_child);
+		inform_grandparents(new_child, pParent->parent());
+	}
+}
+
+// find_ordered(const stored_type&)  
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+typename tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::ordered_iterator 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::find_ordered(const stored_type& value) 
+{
+	tree_type tree_node(value);  // search node
+	return ordered_iterator(ordered_children.find(&tree_node));
+}
+
+// find_ordered(const stored_type&) const 
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+typename tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::const_ordered_iterator 
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::find_ordered(const stored_type& value) const
+{
+	tree_type tree_node(value);  // search node
+	return const_ordered_iterator(ordered_children.find(&tree_node));
+}
+
+// erase(const stored_type&)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+bool tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::
+erase(const stored_type& value)
+{
+	const associative_iterator_type it = find_deep(value);  // see if node is a descendant
+	if ( it != associative_tree_type::end() ) {
+		tree_type* const pParent = it.node()->parent();  // it is.  get it's parent
+		tree_type* pAncestor = pParent;
+
+		while ( pAncestor ) {  // update all ancestors of removed child
+			pAncestor->descendents.erase(it.node());
+			pAncestor = pAncestor->parent();
+		}
+
+		tree_type* const pNode = it.node();
+		pParent->ordered_children.erase(pNode);
+		dynamic_cast<associative_tree_type*>(pParent)->erase(*pNode->get()); // erase node
+
+		return true;
+	}
+
+	return false;
+}
+
+// erase(iterator)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+void tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::erase(associative_iterator_type it) 
+{
+	tree_type* pAncestor = this;
+
+	while (pAncestor) { // update all ancestors of removed child
+		pAncestor->descendents.erase(it.node());
+		pAncestor = pAncestor->parent();
+	}
+
+	tree_type* pNode = it.node();
+	ordered_children.erase(pNode);
+
+	associative_tree_type::erase(*pNode->get()); 
+}
+
+// erase(iterator, iterator)
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+void tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::erase(associative_iterator_type it_beg, associative_iterator_type it_end) 
+{
+	while (it_beg != it_end) {
+		erase(it_beg++);
+	}
+}
+
+// check_for_duplicate()
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+bool tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::check_for_duplicate(const stored_type& value, const tree_type* pParent) const
+{
+	while ( pParent && !pParent->is_root() ) {  // find root node
+		pParent = pParent->parent();
+	}
+
+	// check if node is root
+	if (!(value < *pParent->get()) && !(*pParent->get() < value))
+		return true;
+
+	associative_const_iterator_type it = pParent->find_deep(value);  // check if node is descendant of root
+	associative_const_iterator_type it_end = pParent->end();
+
+	return ( it != it_end );  
+}
+
+// get_root()
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+const tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>*
+tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::get_root() const
+{
+	const tree_type* pParent = this;
+
+	while ( pParent->parent() ) {  // traverse up to root
+		pParent = pParent->parent();
+	}
+
+	return pParent;
+}
+
+// swap
+template<typename stored_type, typename node_compare_type, typename node_order_compare_type>
+void tcl::unique_tree<stored_type, node_compare_type, node_order_compare_type>::swap(tree_type& rhs)
+{
+	tree_type temp(*this);
+
+	clear();
+	*this = rhs;
+
+	rhs.clear();
+	rhs = temp;
+}

BIN
comx_sdk.node/include/ModelIO/BaseIO.rar


File diff suppressed because it is too large
+ 1316 - 0
comx_sdk.node/include/ModelIO/BaseIO/BaseIO.h


+ 110 - 0
comx_sdk.node/include/ModelIO/CurveAdaptiveDiscrete.h

@@ -0,0 +1,110 @@
+/*******************************************************************************
+
+程序说明
+
+曲线离散程序,对Curve数据进行离散,用于后续的显示;
+
+*******************************************************************************/
+
+#ifndef CURVEADAPTIVEDISCRETE_H
+#define CURVEADAPTIVEDISCRETE_H
+
+#include <vector>
+#include <BRepAdaptor_Curve.hxx>
+#include <GCPnts_QuasiUniformDeflection.hxx>
+#include <GCPnts_TangentialDeflection.hxx>
+#include <GCPnts_UniformDeflection.hxx>
+
+using namespace std;
+
+enum CurveDiscreteMethod {
+        TangentialDeflection = 0,
+        QuasiUniformDeflection = 1,
+        UniformDeflection = 2
+};
+
+
+void CurveAdaptiveDiscrete(const BRepAdaptor_Curve &adaptorCurve,
+                                 vector<double> &points, vector<int> &lines,
+                                 CurveDiscreteMethod discreteMethod) {
+
+        points.clear();
+        lines.clear();
+
+        Standard_Integer pointsLength = 0;
+
+        double edgeLength = CPnts_AbscissaPoint::Length(adaptorCurve, 1e-7);
+        // double adaptingDeflection = 0.1 * edgeLength;
+
+        switch (discreteMethod) {
+        case TangentialDeflection: {
+
+                double adaptingDeflection = 0.005 * edgeLength;
+                GCPnts_TangentialDeflection thePointsOnCurve;
+                Standard_Real AngularDeflection = 0.3;
+                Standard_Real CurvatureDeflection = adaptingDeflection;
+                thePointsOnCurve.Initialize(adaptorCurve, AngularDeflection,
+                                            CurvatureDeflection);
+                pointsLength = thePointsOnCurve.NbPoints();
+
+                for (Standard_Integer i = 1; i <= pointsLength; ++i) {
+                        gp_Pnt pt;
+
+                        pt = adaptorCurve.Value(thePointsOnCurve.Parameter(i));
+
+                        points.push_back(pt.X());
+                        points.push_back(pt.Y());
+                        points.push_back(pt.Z());
+
+                        if (i != pointsLength) {
+                                lines.push_back(i - 1);
+                                lines.push_back(i);
+                        }
+                }
+        } break;
+        case QuasiUniformDeflection: {
+
+                double adaptingDeflection = 0.007 * edgeLength;
+                GCPnts_QuasiUniformDeflection thePointsOnCurve;
+                thePointsOnCurve.Initialize(adaptorCurve, adaptingDeflection);
+                pointsLength = thePointsOnCurve.NbPoints();
+                for (Standard_Integer i = 1; i <= pointsLength; ++i) {
+                        gp_Pnt pt;
+
+                        pt = adaptorCurve.Value(thePointsOnCurve.Parameter(i));
+
+                        points.push_back(pt.X());
+                        points.push_back(pt.Y());
+                        points.push_back(pt.Z());
+
+                        if (i != pointsLength) {
+                                lines.push_back(i - 1);
+                                lines.push_back(i);
+                        }
+                }
+        } break;
+        default: {
+                // cout << "UniformDeflection" << endl;
+                GCPnts_UniformDeflection thePointsOnCurve;
+                double adaptingDeflection = 0.007 * edgeLength;
+                thePointsOnCurve.Initialize(adaptorCurve, adaptingDeflection);
+                pointsLength = thePointsOnCurve.NbPoints();
+                for (Standard_Integer i = 1; i <= pointsLength; ++i) {
+                        gp_Pnt pt;
+
+                        pt = adaptorCurve.Value(thePointsOnCurve.Parameter(i));
+
+                        points.push_back(pt.X());
+                        points.push_back(pt.Y());
+                        points.push_back(pt.Z());
+
+                        if (i != pointsLength) {
+                                lines.push_back(i - 1);
+                                lines.push_back(i);
+                        }
+                }
+        } break;
+        }
+}
+
+#endif

+ 286 - 0
comx_sdk.node/include/ModelIO/FaceProperty.h

@@ -0,0 +1,286 @@
+
+/*******************************************************************************
+
+程序说明
+
+Poly_Connect_ex.h:
+	这个文件的基础文件是Opencascade的Poly_Connect.hxx
+	由于调用Poly_Connect类计算法线时,会出现程序执行完毕,polyedge释放错误的Bug,
+	因此在原来的基础上重新对文件进行了编辑,实际Poly_Connect.hxx文件中包含释放polyedge代码
+	但是,注释掉了,因此将这段重新打开;
+
+计算法线注释掉的ComputeNormals()函数是通过计算相邻单元的平均法线法计算的法线,不准确
+保留的ComputeNormals()函数是通过OCC内部函数,基于几何,计算曲面上点的法线方向
+
+*******************************************************************************/
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <TopoDS_Face.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TopLoc_Location.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <Poly_Triangle.hxx>
+#include <Quantity_Color.hxx>
+#include <TDF_Label.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TDF_Tool.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <Geom_Surface.hxx>
+
+#include "Poly_Connect_ex.h"
+
+using namespace std;
+
+enum EdgeType
+{
+	FreeEdge,		// Single Edge in Ansa
+	InnerEdge,		// Double Edge in Ansa
+	ShareEdge		// Triple Edge in Ansa
+};
+
+struct EdgeProperty
+{
+	EdgeType edgeType;
+	int id;
+	vector<int> edges;
+};
+
+inline bool operator<(const EdgeProperty& p1, const EdgeProperty& p2)
+{
+	if (p1.edges < p2.edges)
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+class FaceProperty
+{
+public:
+	FaceProperty()
+	{
+		red = 0;
+		green = 0;
+		blue = 255;
+		label = "Null";
+		name = "NoName";
+	}
+
+	int red;
+	int green;
+	int blue;
+
+	int id;
+
+	//int faceId;
+	////int alpha;
+	//int sid;
+
+	//int hashCode;
+
+	TopoDS_Face faceObj;
+
+	//unsigned long long faceAddress;
+
+	string label;
+	string name;
+	int fatherId;
+
+	// 这里重新构建节点单元法线的数据结构,而不是使用OCC中的已有的数据,原因是构建的数据可以直接输入到OpenGL中
+	// 否则,DCiP中进行渲染时,一样需要建立相同的vector,才能把结果传递到渲染引擎
+	vector<double> points;
+	vector<double> normals;
+	vector<int> elements;
+	set<EdgeProperty> edgeProperties;
+public:
+	void BuildPoints(const TColgp_Array1OfPnt &aNodes, const TopLoc_Location &location)
+	{
+		//for (TColgp_Array1OfPnt::Iterator anIter(aNodes); anIter.More(); anIter.Next())
+		for (int i = 1; i <= aNodes.Length(); i++)
+		{
+			gp_Pnt vertex = aNodes.Value(i).Transformed(location.Transformation());
+
+			points.push_back(vertex.X());
+			points.push_back(vertex.Y());
+			points.push_back(vertex.Z());
+		}
+	}
+
+	void BuildElements(const Poly_Array1OfTriangle &aTri)
+	{
+		for (Standard_Integer i = 1; i <= aTri.Length(); i++)
+		{
+			Standard_Integer nVertexIndex1 = 0;
+			Standard_Integer nVertexIndex2 = 0;
+			Standard_Integer nVertexIndex3 = 0;
+
+			Poly_Triangle aTriangle = aTri.Value(i);
+			aTriangle.Get(nVertexIndex1, nVertexIndex2, nVertexIndex3);
+
+			// -1是为了从1开始变为0开始
+			elements.push_back(nVertexIndex1 - 1);
+			elements.push_back(nVertexIndex2 - 1);
+			elements.push_back(nVertexIndex3 - 1);
+		}
+	}
+
+	void SetColor(Quantity_Color& aColor)
+	{
+		red = int(aColor.Red() * 255);
+		green = int(aColor.Green() * 255);
+		blue = int(aColor.Blue() * 255);
+	}
+
+	void SetFaceLabel(const TDF_Label& _label)
+	{
+		TCollection_AsciiString entry;
+		TDF_Tool::Entry(_label, entry);
+		label = entry.ToCString();
+	}
+	//*
+	//OCC获取节点法线,更精确
+	void ComputeNormals()
+	{
+		TopLoc_Location location;
+		Handle(Poly_Triangulation) theTris = BRep_Tool::Triangulation(faceObj, location);
+
+		if (theTris.IsNull())
+		{
+			return;
+		}
+		if (theTris->HasNormals()) {
+
+			//normals = POLY_TRIGULATION_NORMALS(theTris);
+			return;
+		}
+
+		// take in face the surface location
+		const TopoDS_Face aZeroFace =
+			TopoDS::Face(faceObj.Located(TopLoc_Location()));
+		Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aZeroFace);
+		const Poly_Array1OfTriangle &aTriangles = POLY_TRIGULATION_TRIANGLES(theTris);
+		if (!theTris->HasUVNodes() || aSurf.IsNull()) {
+			// compute normals by averaging triangulation normals sharing
+			// the same vertex
+			Poly::ComputeNormals(theTris);
+			return;
+		}
+
+		const Standard_Real aTol = Precision::Confusion();
+		//const TColgp_Array1OfPnt2d &aNodesUV = theTris->UVNodes();
+		const TColgp_Array1OfPnt2d &aNodesUV = POLY_TRIGULATION_UVNODES(theTris);
+		//const TColgp_Array1OfPnt &aNodes = theTris->Nodes();
+		const TColgp_Array1OfPnt &aNodes = POLY_TRIGULATION_NODES(theTris);
+		gp_Dir aNorm;
+
+		for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
+		{
+			if (GeomLib::NormEstim(aSurf, aNodesUV.Value(aNodeIter), aTol, aNorm) > 1)
+			{
+				Poly_Connect_Ex thePolyConnect;
+				thePolyConnect.Load(theTris);
+
+				// compute flat normals
+				gp_XYZ eqPlan(0.0, 0.0, 0.0);
+				Standard_Integer aTri[3];
+				for (thePolyConnect.Initialize(aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
+				{
+					aTriangles(thePolyConnect.Value()).Get(aTri[0], aTri[1], aTri[2]);
+					const gp_XYZ v1(aNodes(aTri[1]).Coord() - aNodes(aTri[0]).Coord());
+					const gp_XYZ v2(aNodes(aTri[2]).Coord() - aNodes(aTri[1]).Coord());
+					const gp_XYZ vv = v1 ^ v2;
+					const Standard_Real aMod = vv.Modulus();
+					if (aMod >= aTol) {
+						eqPlan += vv / aMod;
+					}
+				}
+				const Standard_Real aModMax = eqPlan.Modulus();
+				aNorm = (aModMax > aTol) ? gp_Dir(eqPlan) : gp::DZ();
+			}
+
+			normals.push_back(aNorm.X());
+			normals.push_back(aNorm.Y());
+			normals.push_back(aNorm.Z());
+		}
+
+	}
+	//*/
+	/*
+	// 平均法线法计算节点法线
+	void ComputeNormals()
+	{
+		normals.resize(points.size());
+
+		for (unsigned int i = 0, il = elements.size(); i < il; i += 3) {
+
+			// elements从1开始,而不是0,所以-1
+			int vA = elements[i + 0];
+			int vB = elements[i + 1];
+			int vC = elements[i + 2];
+
+			if (vA == 0 || vB == 0 || vC == 0)
+			{
+				int a = 1;
+			}
+
+			gp_Vec pA(points[vA * 3], points[vA * 3 + 1], points[vA * 3 + 2]);
+			gp_Vec pB(points[vB * 3], points[vB * 3 + 1], points[vB * 3 + 2]);
+			gp_Vec pC(points[vC * 3], points[vC * 3 + 1], points[vC * 3 + 2]);
+
+			gp_Vec cb = pC - pB;
+			gp_Vec ab = pA - pB;
+			cb = cb ^ ab;
+
+			gp_Vec nA(normals[vA * 3], normals[vA * 3 + 1], normals[vA * 3 + 2]);
+			gp_Vec nB(normals[vB * 3], normals[vB * 3 + 1], normals[vB * 3 + 2]);
+			gp_Vec nC(normals[vC * 3], normals[vC * 3 + 1], normals[vC * 3 + 2]);
+
+			nA = nA + cb;
+			nB = nB + cb;
+			nC = nC + cb;
+
+			normals[vA * 3] = nA.X();
+			normals[vA * 3 + 1] = nA.Y();
+			normals[vA * 3 + 2] = nA.Z();
+
+			normals[vB * 3] = nB.X();
+			normals[vB * 3 + 1] = nB.Y();
+			normals[vB * 3 + 2] = nB.Z();
+
+			normals[vC * 3] = nC.X();
+			normals[vC * 3 + 1] = nC.Y();
+			normals[vC * 3 + 2] = nC.Z();
+		}
+
+		for (unsigned int i = 0, il = normals.size(); i < il; i += 3) {
+			gp_XYZ _nor(normals[i], normals[i + 1], normals[i + 2]);
+
+			const Standard_Real aModMax = _nor.Modulus();
+			gp_Dir aNorm = (aModMax > 1e-6) ? gp_Dir(_nor) : gp::DZ();
+
+			normals[i] = aNorm.X();
+			normals[i + 1] = aNorm.Y();
+			normals[i + 2] = aNorm.Z();
+		}
+	}
+	*/
+	void Dump()
+	{
+		cout << "Face Property: " << endl;
+		cout << "Color Red  : " << red << endl;
+		cout << "Color Green: " << green << endl;
+		cout << "Color Blue : " << blue << endl;
+		cout << "id   : " << id << endl;
+		cout << "points size: " << points.size() << endl;
+		cout << "elems  size: " << elements.size() << endl;
+		cout << endl;
+	}
+
+};

+ 309 - 0
comx_sdk.node/include/ModelIO/GeoAPIUtil.h

@@ -0,0 +1,309 @@
+/*******************************************************************************
+
+程序说明
+
+提供了一些处理模型的方法,ModelIO.h中并未使用
+
+*******************************************************************************/
+
+#ifndef GEOAPIUTIL_H
+#define GEOAPIUTIL_H
+
+#include <XCAFApp_Application.hxx>
+#include <BinXCAFDrivers.hxx>
+#include <STEPCAFControl_Writer.hxx>
+#include <gp_Pnt.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopExp_Explorer.hxx>
+#include <GProp_GProps.hxx>
+#include <BRepGProp.hxx>
+#include <Geom_Surface.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepAdaptor_Curve.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepAlgoAPI_Common.hxx>
+#include <BRepPrimAPI_MakeSphere.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+#include <BRepTools.hxx>
+#include <BRepAlgoAPI_Cut.hxx>
+#include <TopoDS.hxx>
+#include <Geom_SphericalSurface.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <STANDARD_TYPE.hxx>
+#include <BRepExtrema_DistShapeShape.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <StlAPI_Writer.hxx>
+#include <GeomAPI_ProjectPointOnSurf.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <gp_Lin.hxx>
+#include <string>
+
+using namespace std;
+
+namespace GeoAPIUtil
+{
+
+	// 获取一个Shape的中心点,是多个Face中心点的平均值
+	// Face为柱面时中心点为中轴的中点
+	// Face为球面时,中心点为圆心
+	inline gp_Pnt GetShapeCentroid(const TopoDS_Shape &shape)
+	{
+		gp_Pnt centroid;
+		int centroidCount = 0;
+		for (TopExp_Explorer faceExp(shape, TopAbs_FACE); faceExp.More(); faceExp.Next())
+		{
+			const TopoDS_Face face = TopoDS::Face(faceExp.Current());
+			const Handle(Geom_Surface)& surface = BRep_Tool::Surface(face);
+
+			gp_Pnt center;
+
+			// 如果是圆柱面则取圆柱的中心,否则计算其质心
+			if (surface->IsInstance(STANDARD_TYPE(Geom_CylindricalSurface)))
+			{
+				Handle(Geom_CylindricalSurface) cylindricalSurface = Handle(Geom_CylindricalSurface)::DownCast(surface);
+				center = cylindricalSurface->Location();
+			}
+			else if (surface->IsInstance(STANDARD_TYPE(Geom_SphericalSurface)))
+			{
+				Handle(Geom_SphericalSurface) sphericalSurface = Handle(Geom_SphericalSurface)::DownCast(surface);
+				center = sphericalSurface->Location();
+			}
+			else
+			{
+				GProp_GProps properties;
+				BRepGProp::SurfaceProperties(face, properties);
+				center = properties.CentreOfMass();
+			}
+
+			centroid.SetX(centroid.X() + center.X());
+			centroid.SetX(centroid.Y() + center.Y());
+			centroid.SetX(centroid.Z() + center.Z());
+			centroidCount++;
+		}
+
+		centroid.SetX(centroid.X() / centroidCount);
+		centroid.SetX(centroid.Y() / centroidCount);
+		centroid.SetX(centroid.Z() / centroidCount);
+
+		return centroid;
+	}
+	inline void CreateFaceCentroid(const TopoDS_Face &face, gp_Pnt &center)
+	{
+
+		Handle(Geom_Surface) surface = BRep_Tool::Surface(face);
+
+		// 如果是圆柱面则取圆柱的中心,否则计算其质心
+		if (surface->IsInstance(STANDARD_TYPE(Geom_CylindricalSurface)))
+		{
+			Handle(Geom_CylindricalSurface) cylindricalSurface = Handle(Geom_CylindricalSurface)::DownCast(surface);
+			center = cylindricalSurface->Location();
+		}
+		else if (surface->IsInstance(STANDARD_TYPE(Geom_SphericalSurface)))
+		{
+			Handle(Geom_SphericalSurface) sphericalSurface = Handle(Geom_SphericalSurface)::DownCast(surface);
+			center = sphericalSurface->Location();
+		}
+		else
+		{
+			GProp_GProps properties;
+			BRepGProp::SurfaceProperties(face, properties);
+			center = properties.CentreOfMass();
+		}
+	}
+	// 获取中心点,并且投影到平面上
+	inline void CreateFaceCentroidOnSurface(const TopoDS_Face &face, gp_Pnt &center)
+	{
+		Handle(Geom_Surface) surface = BRep_Tool::Surface(face);
+
+		gp_Pnt _center;
+
+		GProp_GProps properties;
+		BRepGProp::SurfaceProperties(face, properties);
+		_center = properties.CentreOfMass();
+
+		GeomAPI_ProjectPointOnSurf geomProj(_center, surface);
+
+		if (geomProj.IsDone())
+		{
+			double disMin = 1e6;
+
+			for (int i = 1; i <= geomProj.NbPoints(); i++)
+			{
+				gp_Pnt _pt = geomProj.Point(i);
+
+				double squareDis = _center.SquareDistance(_pt);
+				if (squareDis < disMin)
+				{
+					disMin = squareDis;
+					center = _pt;
+				}
+			}
+		}
+		else
+		{
+			center = _center;
+		}
+
+	}
+
+	// 用一个球体截取一个曲面,并且生成BRep数据
+	// 输出为Brep文件,参数依次为球的圆心,半径,以及要裁剪的面TopoDS_Shape类型,最后是输出的BRep文件的路径
+	inline bool SphereSurfaceIntersection(const gp_Pnt &center, const double &R, const TopoDS_Shape &shape, const string &brepfilePath, const string &stlfilePath)
+	{
+		TopoDS_Shape sphereShape = BRepPrimAPI_MakeSphere(center, R);
+
+		TopoDS_Compound aCompound;
+		BRep_Builder    aBuildTool;
+		aBuildTool.MakeCompound(aCompound);
+
+		for (TopExp_Explorer faceExp(shape, TopAbs_FACE); faceExp.More(); faceExp.Next())
+		{
+			TopoDS_Shape shapeChild = faceExp.Current();
+
+			BRepAlgoAPI_Common section(shapeChild, sphereShape);
+			section.Build();
+
+			TopExp_Explorer faceChildExp(section.Shape(), TopAbs_FACE);
+			if (faceChildExp.More())
+			{
+				aBuildTool.Add(aCompound, section.Shape());
+			}
+		}
+
+		if (!BRepTools::Write(aCompound, brepfilePath.c_str()))
+		{
+			return false;
+		}
+
+		BRepMesh_IncrementalMesh anAlgo;
+		anAlgo.ChangeParameters().Deflection = 0.2;
+		anAlgo.ChangeParameters().Angle = 20.0 * M_PI / 180.0; // 20 degrees
+		anAlgo.ChangeParameters().InParallel = true;
+		anAlgo.SetShape(aCompound);
+		anAlgo.Perform();
+
+		StlAPI_Writer anStlWriter;
+
+		if (anStlWriter.Write(aCompound, stlfilePath.c_str()))
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	// 用一个球体截取一个曲面,并且生成TopoDS_Compound
+	// 返回为TopoDS_Compound,参数依次为球的圆心,半径,以及要裁剪的面TopoDS_Shape类型
+	inline TopoDS_Compound SphereSurfaceIntersection(const gp_Pnt &center, const double &R, const TopoDS_Shape &shape)
+	{
+		TopoDS_Shape sphereShape = BRepPrimAPI_MakeSphere(center, R);
+
+		TopoDS_Compound aCompound;
+		BRep_Builder    aBuildTool;
+		aBuildTool.MakeCompound(aCompound);
+
+		for (TopExp_Explorer faceExp(shape, TopAbs_FACE); faceExp.More(); faceExp.Next())
+		{
+			TopoDS_Shape shapeChild = faceExp.Current();
+
+			BRepAlgoAPI_Common section(shapeChild, sphereShape);
+			section.Build();
+
+			TopExp_Explorer faceChildExp(section.Shape(), TopAbs_FACE);
+			if (faceChildExp.More())
+			{
+				aBuildTool.Add(aCompound, section.Shape());
+			}
+		}
+
+		return aCompound;
+	}
+
+	// 删除Face
+	inline void RemoveFace(TopoDS_Shape& shape, const TopoDS_Face& faceToRemove)
+	{
+		BRepAlgoAPI_Cut cut(shape, faceToRemove);
+		TopoDS_Shape resultShape = cut.Shape();
+		shape = resultShape;
+	}
+
+	inline void CreatePoint(const double &x, const double &y, const double &z, gp_Pnt &aPoint)
+	{
+		aPoint.SetCoord(x, y, z);
+
+	}
+	inline void CreatePoint(const double &x, const double &y, const double &z, TopoDS_Vertex &vertex)
+	{
+		gp_Pnt aPoint(x, y, z);
+		vertex = BRepBuilderAPI_MakeVertex(aPoint);
+	}
+
+	inline bool GetLineSurfaceIntersectionPoint(const gp_Pnt &pt, const gp_Dir &dir, const TopoDS_Face &face, gp_Pnt &intersectionPoint)
+	{
+		gp_Lin line(pt, dir);
+		TopoDS_Edge lineEdge = BRepBuilderAPI_MakeEdge(line);
+		BRepExtrema_DistShapeShape distSS(lineEdge, face, Extrema_ExtFlag_MIN);
+		distSS.Perform();
+
+		if (distSS.IsDone() && distSS.NbSolution() > 0 && distSS.Value() < 1e-3)
+		{
+			double minDistance = 1e6;
+			for (int i = 1; i <= distSS.NbSolution(); i++)
+			{
+
+				double dis = distSS.PointOnShape2(i).Distance(pt);
+
+				if (dis < minDistance)
+				{
+					minDistance = dis;
+					intersectionPoint = distSS.PointOnShape2(i);
+				}
+			}
+
+			return true;
+		}
+		else {
+			return false;
+		}
+	}
+
+	inline bool CreateStpByShape(const TopoDS_Shape& aShape, const string &filePath)
+	{
+		Handle(TDocStd_Document) localDoc;
+		Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
+		BinXCAFDrivers::DefineFormat(anApp);
+		anApp->NewDocument("BinXCAF", localDoc);
+		Handle(XCAFDoc_ShapeTool)shapeTool = XCAFDoc_DocumentTool::ShapeTool(localDoc->Main());
+
+		// 将形状添加到文档中
+		TDF_Label label;
+		shapeTool->AddShape(aShape);
+
+		STEPControl_StepModelType mode = STEPControl_AsIs;
+
+		STEPCAFControl_Writer aWriter;
+		aWriter.SetColorMode(true);
+		aWriter.SetNameMode(true);
+
+		// Translating document (conversion) to STEP
+		if (!aWriter.Transfer(localDoc, mode)) {
+			return false;
+		}
+		// Writing the File
+		IFSelect_ReturnStatus status = aWriter.Write(filePath.c_str());
+
+		// 检查是否成功写入
+		if (status != IFSelect_RetDone) {
+			return false;
+		}
+
+		return true;
+	}
+
+
+};
+#endif // GEOAPIUTIL_H

+ 1 - 0
comx_sdk.node/include/ModelIO/ModelDistance.h

@@ -0,0 +1 @@
+#include "BaseIO.h"

+ 246 - 0
comx_sdk.node/include/ModelIO/MurmurHash.h

@@ -0,0 +1,246 @@
+/*******************************************************************************
+
+程序说明
+
+计算Hash值的函数,参考7.8.0版本的计算哈希值函数,调用方式与7.8.0一致
+
+*******************************************************************************/
+
+#ifndef MURMURHASH_H
+#define MURMURHASH_H
+
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopLoc_Datum3D.hxx>
+#include <TopLoc_SListOfItemLocation.hxx>
+#include <TopLoc_Location.hxx>
+#include <TopLoc_ItemLocation.hxx>
+#include <string>
+
+namespace opencascade
+{
+	namespace MurmurHash
+	{
+		inline uint64_t shift_mix(uint64_t theV)
+		{
+			return theV ^ (theV >> 47);
+		}
+
+		// Loads n bytes, where 1 <= n < 8.
+		inline uint64_t load_bytes(const char* thePnt, int theNb)
+		{
+			uint64_t aRes = 0;
+			--theNb;
+			do
+				aRes = (aRes << 8) + static_cast<unsigned char>(thePnt[theNb]);
+			while (--theNb >= 0);
+			return aRes;
+		}
+		template <typename T>
+		inline T unaligned_load(const char* thePnt)
+		{
+			T aRes;
+			memcpy(&aRes, thePnt, sizeof(aRes));
+			return aRes;
+		}
+
+		//=======================================================================
+		//function : MurmurHash64A
+		//purpose  :
+		//=======================================================================
+		inline uint64_t MurmurHash64A(const void* theKey, int theLen, uint64_t theSeed)
+		{
+			static constexpr uint64_t aMul = (((uint64_t)0xc6a4a793UL) << 32UL)
+				+ (uint64_t)0x5bd1e995UL;
+			const char* const aBuf = static_cast<const char*>(theKey);
+
+			// Remove the bytes not divisible by the sizeof(uint64_t).  This
+			// allows the main loop to process the data as 64-bit integers.
+			const uint64_t aLenAligned = theLen & ~(uint64_t)0x7;
+			const char* const anEnd = aBuf + aLenAligned;
+			uint64_t aHash = theSeed ^ (theLen * aMul);
+			for (const char* aPnt = aBuf; aPnt != anEnd; aPnt += 8)
+			{
+				const uint64_t aData = shift_mix(unaligned_load<uint64_t>(aPnt) * aMul) * aMul;
+				aHash ^= aData;
+				aHash *= aMul;
+			}
+			if ((theLen & 0x7) != 0)
+			{
+				const uint64_t data = load_bytes(anEnd, theLen & 0x7);
+				aHash ^= data;
+				aHash *= aMul;
+			}
+			aHash = shift_mix(aHash) * aMul;
+			aHash = shift_mix(aHash);
+			return aHash;
+		}
+
+		//=======================================================================
+		//function : MurmurHash2A
+		//purpose  :
+		//=======================================================================
+		inline uint32_t MurmurHash2A(const void* theKey, int theLen, uint32_t theSeed)
+		{
+			const uint32_t aMul = 0x5bd1e995;
+			uint32_t aHash = theSeed ^ theLen;
+			const char* aBuf = static_cast<const char*>(theKey);
+
+			// Mix 4 bytes at a time into the hash.
+			while (theLen >= 4)
+			{
+				uint32_t aKey = unaligned_load<uint32_t>(aBuf);
+				aKey *= aMul;
+				aKey ^= aKey >> 24;
+				aKey *= aMul;
+				aHash *= aMul;
+				aHash ^= aKey;
+				aBuf += 4;
+				theLen -= 4;
+			}
+
+			uint32_t aKey;
+			// Handle the last few bytes of the input array.
+			switch (theLen)
+			{
+			case 3:
+				aKey = static_cast<unsigned char>(aBuf[2]);
+				aHash ^= aKey << 16;
+				Standard_FALLTHROUGH
+			case 2:
+				aKey = static_cast<unsigned char>(aBuf[1]);
+				aHash ^= aKey << 8;
+				Standard_FALLTHROUGH
+			case 1:
+				aKey = static_cast<unsigned char>(aBuf[0]);
+				aHash ^= aKey;
+				aHash *= aMul;
+			};
+
+			// Do a few final mixes of the hash.
+			aHash ^= aHash >> 13;
+			aHash *= aMul;
+			aHash ^= aHash >> 15;
+			return aHash;
+		}
+
+
+		template <typename T1, typename T = size_t>
+		typename std::enable_if<sizeof(T) == 8, uint64_t>::type
+			hash_combine(const T1& theValue, const int theLen = sizeof(T1), const T theSeed = 0xA329F1D3A586ULL)
+		{
+			return MurmurHash::MurmurHash64A(&theValue, theLen, theSeed);
+		}
+
+		template <typename T1, typename T = size_t>
+		typename std::enable_if<sizeof(T) != 8, T>::type
+			hash_combine(const T1& theValue, const int theLen = sizeof(T1), const T theSeed = 0xc70f6907U)
+		{
+			return static_cast<T>(MurmurHash::MurmurHash2A(&theValue, theLen, theSeed));
+		}
+
+		template <typename T = size_t>
+		constexpr T optimalSeed()
+		{
+			return sizeof(T) == 8 ? static_cast<T>(0xA329F1D3A586ULL) : static_cast<T>(0xc70f6907U);
+		}
+	};
+
+	template <typename T1, typename T = size_t>
+	T hash(const T1 theValue) noexcept
+	{
+		return opencascade::MurmurHash::hash_combine<T1, T>(theValue);
+	}
+
+	template <typename T1, typename T = size_t>
+	T hashBytes(const T1* theKey, int theLen)
+	{
+		return opencascade::MurmurHash::hash_combine<T1, T>(*theKey, theLen);
+	}
+
+	template <typename T1, typename T = size_t>
+	T hash_combine(const T1 theValue, const int theLen, const T theSeed)
+	{
+		return opencascade::MurmurHash::hash_combine<T1, T>(theValue, theLen, theSeed);
+	}
+};
+
+
+namespace std
+{
+	inline size_t GetLocationHashCode(const TopLoc_Location& loc)
+	{
+		gp_Trsf T = loc.Transformation();
+		TopLoc_SListOfItemLocation myItems;
+		Handle(TopLoc_Datum3D) D = new TopLoc_Datum3D(T);
+		myItems.Construct(TopLoc_ItemLocation(D, 1));
+
+		// Hashing base on IsEqual function
+		if (myItems.IsEmpty())
+		{
+			return 0;
+		}
+		size_t aHash = opencascade::MurmurHash::optimalSeed<size_t>();
+		TopLoc_SListOfItemLocation items = myItems;
+		size_t aCombined[3];
+		while (items.More())
+		{
+			//aCombined[0] = std::hash<Handle(TopLoc_Datum3D)>{}(items.Value().myDatum);
+			aCombined[0] = static_cast<size_t>(reinterpret_cast<std::uintptr_t>(D.get()));
+			aCombined[1] = opencascade::hash(1);
+			aCombined[2] = aHash;
+			aHash = opencascade::hashBytes(aCombined, sizeof(aCombined));
+			items.Next();
+		}
+		return aHash;
+	}
+
+	template <class TheTransientType>
+	struct hash<Handle(TheTransientType)>
+	{
+		size_t operator()(const Handle(TheTransientType)& theHandle) const noexcept
+		{
+			return static_cast<size_t>(reinterpret_cast<std::uintptr_t>(theHandle.get()));
+		}
+	};
+
+	template <>
+	struct hash<TopLoc_Location>
+	{
+		size_t operator()(const TopLoc_Location& theLocation) const
+		{
+			return std::GetLocationHashCode(theLocation);
+		}
+	};
+
+	template <>
+	struct hash<TopoDS_Shape>
+	{
+		size_t operator()(const TopoDS_Shape& theShape) const noexcept
+		{
+			const size_t aHL = std::hash<TopLoc_Location>{}(theShape.Location());
+			return aHL == 0 ? opencascade::hash(theShape.TShape().get())
+				: opencascade::MurmurHash::hash_combine(theShape.TShape().get(), sizeof(void*), aHL);
+		}
+	};
+
+	template <>
+	struct hash<TopoDS_Face>
+	{
+		size_t operator()(const TopoDS_Face& theShape) const
+		{
+			return std::hash<TopoDS_Shape>{}(theShape);
+		}
+	};
+
+	template <>
+	struct hash<TopoDS_Edge>
+	{
+		size_t operator()(const TopoDS_Edge& theShape) const
+		{
+			return std::hash<TopoDS_Shape>{}(theShape);
+		}
+	};
+};
+#endif // MURMURHASH_H

+ 76 - 0
comx_sdk.node/include/ModelIO/RandomColorGenerator.h

@@ -0,0 +1,76 @@
+/*******************************************************************************
+
+	基于HSV色彩模式定义的一个颜色生成器,过滤掉一些不适合显示模型的颜色,比如纯色
+	另外,生成的相邻颜色差别也较大,避免颜色过于相似
+
+*******************************************************************************/
+
+
+#pragma once
+
+#include <Quantity_Color.hxx>
+#include <vector>
+
+#define HUESTEP			360
+#define SATURATIONSTEP	17
+#define LIGHTNESSSTEP	19
+
+
+class RandomColorGenerator
+{
+public:
+	RandomColorGenerator() {
+		Ref = 0;
+		for (int i = 1; i <= HUESTEP; i++)
+		{
+			HueSamplers.push_back((83 * i) % HUESTEP);
+		}
+
+		// 饱和度 0.0 - 1.0
+		for (int i = 1; i <= SATURATIONSTEP; i++)
+		{
+			double randomNum = (7 * i) % SATURATIONSTEP;
+			SaturationSamplers.push_back(0.5 * randomNum / SATURATIONSTEP + 0.5);
+		}
+
+		// 亮度 0.2 - 0.8
+		for (int i = 1; i <= LIGHTNESSSTEP; i++)
+		{
+			int randomNum = (11 * i) % LIGHTNESSSTEP;
+			LightSamplers.push_back(0.5 * randomNum / LIGHTNESSSTEP + 0.5);
+		}
+
+	}
+	~RandomColorGenerator() {}
+
+	Quantity_Color GetColor()
+	{
+		int indexHue = Ref % HUESTEP;
+		int indexSaturation = Ref % SATURATIONSTEP;
+		int indexLight = Ref % LIGHTNESSSTEP;
+
+		color.SetValues(HueSamplers[indexHue], LightSamplers[indexLight], SaturationSamplers[indexSaturation], Quantity_TOC_HLS);
+		Ref++;
+
+		return color;
+	}
+
+	void ResetRef()
+	{
+		Ref = 0;
+	}
+
+	void SetRefBegin(const int _Ref)
+	{
+		Ref = _Ref;
+	}
+
+
+private:
+	int Ref;
+	std::vector<int> HueSamplers;
+	std::vector<double> SaturationSamplers;
+	std::vector<double> LightSamplers;
+	Quantity_Color color;
+
+};

+ 158 - 0
comx_sdk.node/include/ModelIO/TreeLabel.h

@@ -0,0 +1,158 @@
+/*******************************************************************************
+
+用于显示模型的结构树
+
+根节点名称定义为Model
+
+节点分为两种类型,一种为TreeShape,包含子节点,但不包含具体的Face的数据,faceId均为0;
+一种为TreeFace,从属于TreeShape,存储了真正的Face数据,faceId大于0;
+
+
+*******************************************************************************/
+
+
+#pragma once
+
+#include <TopoDS_Shape.hxx>
+#include <TDF_Label.hxx>
+#include <string>
+#include <vector>
+
+//#define UPPERBOUND		2147483647
+#define UPPERBOUND			1999999999
+
+using namespace std;
+
+enum TreeType
+{
+	TreeShape,
+	TreeFace
+};
+struct TreeLabel
+{
+	TreeLabel()
+	{
+		id = 0;
+		Name = "Model";
+	}
+	TreeLabel(const TopoDS_Shape &_Shape, TreeType _NodeType = TreeShape, int _Level = 0) :
+		Shape(_Shape), NodeType(_NodeType), Level(_Level)
+	{
+		Name = GetName();
+	}
+	TreeLabel(const TDF_Label &_Label, const TopoDS_Shape &_Shape, TreeType _NodeType = TreeShape, int _Level = 0) :
+		Label(_Label), Shape(_Shape), NodeType(_NodeType), Level(_Level)
+	{
+		Name = GetName();
+	}
+
+	TDF_Label Label;
+	TopoDS_Shape Shape;
+	TreeType NodeType;
+	int id;
+	int Level;	
+	string Name;
+	vector<int> subFaceIds;
+	//int HashCode;
+	//int faceId;
+	//int sid;
+	//vector<int> subFaceHashCodes;
+
+	friend bool operator < (const TreeLabel& lhs, const TreeLabel& rhs)
+	{
+		return lhs.id < rhs.id;
+	}
+	friend bool operator == (const TreeLabel& lhs, const TreeLabel& rhs)
+	{
+		return lhs.id == rhs.id;
+	}
+
+	string GetName()
+	{
+		TCollection_ExtendedString str = "";
+
+		if (Label.IsNull() && Shape.IsNull())
+		{
+			str = "Model";
+		}
+
+		if (!Label.IsNull())
+		{
+			Handle(TDataStd_Name) anAttribute;
+
+			if (Label.FindAttribute(TDataStd_Name::GetID(), anAttribute))
+			{
+				str = anAttribute->Get();
+			}
+		}
+
+		if (str == "")
+		{
+			switch (Shape.ShapeType())
+			{
+			case TopAbs_COMPOUND:
+				str = "Compound";
+				break;
+			case TopAbs_COMPSOLID:
+				str = "CSolid";
+				break;
+			case TopAbs_SOLID:
+				str = "Solid";
+				break;
+			case  TopAbs_SHELL:
+				str = "Shell";
+				break;
+			case TopAbs_FACE:
+				str = "Face";
+				break;
+			case TopAbs_WIRE:
+				str = "Wire";
+				break;
+			case TopAbs_EDGE:
+				str = "Edge";
+				break;
+			case TopAbs_VERTEX:
+				str = "Vertex";
+				break;
+			case TopAbs_SHAPE:
+				str = "Shape";
+				break;
+			default:
+				break;
+			}
+		}
+
+		char* ch = new char[str.LengthOfCString() + 1];
+		str.ToUTF8CString(ch);
+		return ch;
+	}
+
+	string GetJsonName()
+	{
+		string tail;
+
+		//if (id < 10)
+		//{
+		//	tail = "_0000" + to_string(id);
+		//}
+		//else if (id < 100)
+		//{
+		//	tail = "_000" + to_string(id);
+		//}
+		//else if (id < 1000)
+		//{
+		//	tail = "_00" + to_string(id);
+		//}
+		//else if (id < 10000)
+		//{
+		//	tail = "_0" + to_string(id);
+		//}
+		//else
+		//{
+		//	tail = "_" + to_string(id);
+		//}
+
+		tail = "_" + to_string(id);
+		return Name + tail;
+	}
+};

+ 96 - 0
comx_sdk.node/include/ModelIO/occ_compatible.h

@@ -0,0 +1,96 @@
+/*******************************************************************************
+
+³ÌÐò˵Ã÷
+
+½â¾öOCC7.5Óë7.8¼æÈÝÐÔ
+
+*******************************************************************************/
+
+#ifndef OCC_COMPATIBLE_H
+#define OCC_COMPATIBLE_H
+
+#include <vector>
+#include <Standard_Version.hxx>
+
+using namespace std;
+
+namespace occ_compatible
+{
+	//
+//#define OCCT_VERSION_LESS_THAN_7_8 \
+//    ((OCC_VERSION_MAJOR < 7) || \
+//    ((OCC_VERSION_MAJOR == 7) && (OCC_VERSION_MINOR < 8)))
+
+#define OCC_VERSION_OPTION_7_5 ((OCC_VERSION_MAJOR == 7) && (OCC_VERSION_MINOR == 5))
+#define OCC_VERSION_OPTION_7_8 ((OCC_VERSION_MAJOR == 7) && (OCC_VERSION_MINOR == 8))
+
+#if OCC_VERSION_OPTION_7_5
+vector<double> GetNormals(opencascade::handle<Poly_Triangulation> theTris)
+{
+	vector<double> res;
+	for (int i = 1; i <= theTris->Normals().Size(); i++)
+	{
+		res.push_back(theTris->Normals().Value(i));
+	}
+	return res;
+}
+
+
+#define POLY_TRIGULATION_TRIANGLES(triFace) triFace->Triangles()
+#define POLY_TRIGULATION_NODES(triFace) triFace->Nodes()
+#define POLY_TRIGULATION_NORMALS(triFace) occ_compatible::GetNormals(triFace)
+#define POLY_TRIGULATION_UVNODES(triFace) triFace->UVNodes()
+
+
+#elif OCC_VERSION_OPTION_7_8
+#include <gp_Vec3f.hxx>
+
+	TColgp_Array1OfPnt GetNodes(opencascade::handle<Poly_Triangulation> theTris)
+	{
+		const Poly_ArrayOfNodes &aNodes = theTris->InternalNodes();
+		TColgp_Array1OfPnt aPnt(1, aNodes.Size());
+		for (int i = 1; i <= aNodes.Size(); i++)
+		{
+			gp_Pnt pt = aNodes.Value(i - 1);
+			aPnt[i] = pt;
+		}
+
+		return aPnt;
+	}
+
+	vector<double> GetNormals(opencascade::handle<Poly_Triangulation> theTris)
+	{
+		vector<double> res;
+		NCollection_Array1<gp_Vec3f> aNormals = theTris->InternalNormals();
+		for (int i = 1; i <= aNormals.Size(); i++)
+		{
+			res.push_back(aNormals.Value(i - 1).x());
+			res.push_back(aNormals.Value(i - 1).y());
+			res.push_back(aNormals.Value(i - 1).z());
+		}
+		return res;
+	}
+
+	TColgp_Array1OfPnt2d GetUVNodes(opencascade::handle<Poly_Triangulation> theTris)
+	{
+		const Poly_ArrayOfUVNodes &aNodes = theTris->InternalUVNodes();
+		cout << "aNodes Size: " << aNodes.Size() << endl;
+		TColgp_Array1OfPnt2d aPnt(1, aNodes.Size());
+		for (int i = 1; i <= aNodes.Size(); i++)
+		{
+			aPnt[i] = aNodes.Value(i - 1);
+		}
+
+		return aPnt;
+	}
+	
+
+#define POLY_TRIGULATION_TRIANGLES(triFace) triFace->InternalTriangles()
+#define POLY_TRIGULATION_NODES(triFace) occ_compatible::GetNodes(triFace)
+#define POLY_TRIGULATION_NORMALS(triFace) occ_compatible::GetNormals(triFace)
+#define POLY_TRIGULATION_UVNODES(triFace) occ_compatible::GetUVNodes(triFace)
+#endif
+};
+
+
+#endif

+ 459 - 0
comx_sdk.node/include/ModelIO/poly_connect_ex.h

@@ -0,0 +1,459 @@
+/*******************************************************************************
+
+程序说明
+
+该文件源于poly_connect.hxx
+
+由于使用poly_connect进行法线的计算时,当程序执行完毕释放内存时会出现错误;
+所以在poly_connect.hxx的基础上进行了更改,将Load函数进行了更改,
+加入释放edge array的代码
+
+  // destroy the edges array - can be skipped when using NCollection_IncAllocator
+  for (Standard_Integer aNodeIter = anEdges.Lower(); aNodeIter <= anEdges.Upper(); ++aNodeIter)
+  {
+    for (polyedge* anEdgeIter = anEdges[aNodeIter]; anEdgeIter != NULL;)
+    {
+      polyedge* aTmp = anEdgeIter->next;
+      anIncAlloc->Free (anEdgeIter);
+      anEdgeIter = aTmp;
+    }
+  }
+
+*******************************************************************************/
+
+
+// Created on: 1995-03-06
+// Created by: Laurent PAINNOT
+// Copyright (c) 1995-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Poly_Connect_Ex_HeaderFile
+#define _Poly_Connect_Ex_HeaderFile
+
+#include <Standard.hxx>
+#include <Standard_DefineAlloc.hxx>
+#include <Standard_Handle.hxx>
+
+#include <TColStd_Array1OfInteger.hxx>
+#include <Standard_Integer.hxx>
+#include <Standard_Boolean.hxx>
+
+#include <NCollection_IncAllocator.hxx>
+#include <Poly_Triangle.hxx>
+#include <Poly_Triangulation.hxx>
+
+struct polyedge
+{
+  polyedge* next;         // the next edge in the list
+  Standard_Integer nt[2]; // the two adjacent triangles
+  Standard_Integer nn[2]; // the two adjacent nodes
+  Standard_Integer nd;    // the second node of the edge
+  DEFINE_STANDARD_ALLOC
+};
+
+
+class Poly_Triangulation;
+
+//! Provides an algorithm to explore, inside a triangulation, the
+//! adjacency data for a node or a triangle.
+//! Adjacency data for a node consists of triangles which
+//! contain the node.
+//! Adjacency data for a triangle consists of:
+//! -   the 3 adjacent triangles which share an edge of the triangle,
+//! -   and the 3 nodes which are the other nodes of these adjacent triangles.
+//! Example
+//! Inside a triangulation, a triangle T
+//! has nodes n1, n2 and n3.
+//! It has adjacent triangles AT1, AT2 and AT3 where:
+//! - AT1 shares the nodes n2 and n3,
+//! - AT2 shares the nodes n3 and n1,
+//! - AT3 shares the nodes n1 and n2.
+//! It has adjacent nodes an1, an2 and an3 where:
+//! - an1 is the third node of AT1,
+//! - an2 is the third node of AT2,
+//! - an3 is the third node of AT3.
+//! So triangle AT1 is composed of nodes n2, n3 and an1.
+//! There are two ways of using this algorithm.
+//! -   From a given node you can look for one triangle that
+//! passes through the node, then look for the triangles
+//! adjacent to this triangle, then the adjacent nodes. You
+//! can thus explore the triangulation step by step (functions
+//! Triangle, Triangles and Nodes).
+//! -   From a given node you can look for all the triangles
+//! that pass through the node (iteration method, using the
+//! functions Initialize, More, Next and Value).
+//! A Connect object can be seen as a tool which analyzes a
+//! triangulation and translates it into a series of triangles. By
+//! doing this, it provides an interface with other tools and
+//! applications working on basic triangles, and which do not
+//! work directly with a Poly_Triangulation.
+class Poly_Connect_Ex
+{
+public:
+
+  DEFINE_STANDARD_ALLOC
+
+    //=======================================================================
+    //function : Poly_Connect
+    //purpose  :
+    //=======================================================================
+	  Poly_Connect_Ex()
+    : mytr    (0),
+      myfirst (0),
+      mynode  (0),
+      myothernode (0),
+      mysense (false),
+      mymore  (false)
+    {
+      //
+    }
+
+    //=======================================================================
+    //function : Poly_Connect
+    //purpose  :
+    //=======================================================================
+  Poly_Connect_Ex(const Handle(Poly_Triangulation)& theTriangulation)
+    : myTriangulation (theTriangulation),
+      myTriangles (1, theTriangulation->NbNodes()),
+      myAdjacents (1, 6 * theTriangulation->NbTriangles()),
+      mytr    (0),
+      myfirst (0),
+      mynode  (0),
+      myothernode (0),
+      mysense (false),
+      mymore  (false)
+    {
+      Load (theTriangulation);
+    }
+
+
+  //! Initialize the algorithm to explore the adjacency data of
+  //! nodes or triangles for the triangulation theTriangulation.
+  Standard_EXPORT void Load (const Handle(Poly_Triangulation)& theTriangulation);
+
+  //! Returns the triangulation analyzed by this tool.
+  const Handle(Poly_Triangulation)& Triangulation() const { return myTriangulation; }
+
+  //! Returns the index of a triangle containing the node at
+  //! index N in the nodes table specific to the triangulation analyzed by this tool
+  Standard_Integer Triangle (const Standard_Integer N) const { return myTriangles (N); }
+
+  //! Returns in t1, t2 and t3, the indices of the 3 triangles
+  //! adjacent to the triangle at index T in the triangles table
+  //! specific to the triangulation analyzed by this tool.
+  //! Warning
+  //! Null indices are returned when there are fewer than 3
+  //! adjacent triangles.
+  void Triangles (const Standard_Integer T, Standard_Integer& t1, Standard_Integer& t2, Standard_Integer& t3) const
+  {
+    Standard_Integer index = 6*(T-1);
+    t1 = myAdjacents(index+1);
+    t2 = myAdjacents(index+2);
+    t3 = myAdjacents(index+3);
+  }
+
+  //! Returns, in n1, n2 and n3, the indices of the 3 nodes
+  //! adjacent to the triangle referenced at index T in the
+  //! triangles table specific to the triangulation analyzed by this tool.
+  //! Warning
+  //! Null indices are returned when there are fewer than 3 adjacent nodes.
+  void Nodes (const Standard_Integer T, Standard_Integer& n1, Standard_Integer& n2, Standard_Integer& n3) const
+  {
+    Standard_Integer index = 6*(T-1);
+    n1 = myAdjacents(index+4);
+    n2 = myAdjacents(index+5);
+    n3 = myAdjacents(index+6);
+  }
+
+public:
+
+  //! Initializes an iterator to search for all the triangles
+  //! containing the node referenced at index N in the nodes
+  //! table, for the triangulation analyzed by this tool.
+  //! The iterator is managed by the following functions:
+  //! -   More, which checks if there are still elements in the iterator
+  //! -   Next, which positions the iterator on the next element
+  //! -   Value, which returns the current element.
+  //! The use of such an iterator provides direct access to the
+  //! triangles around a particular node, i.e. it avoids iterating on
+  //! all the component triangles of a triangulation.
+  //! Example
+  //! Poly_Connect C(Tr);
+  //! for
+  //! (C.Initialize(n1);C.More();C.Next())
+  //! {
+  //! t = C.Value();
+  //! }
+  Standard_EXPORT void Initialize (const Standard_Integer N);
+  
+  //! Returns true if there is another element in the iterator
+  //! defined with the function Initialize (i.e. if there is another
+  //! triangle containing the given node).
+  Standard_Boolean More() const { return mymore; }
+
+  //! Advances the iterator defined with the function Initialize to
+  //! access the next triangle.
+  //! Note: There is no action if the iterator is empty (i.e. if the
+  //! function More returns false).-
+  Standard_EXPORT void Next();
+  
+  //! Returns the index of the current triangle to which the
+  //! iterator, defined with the function Initialize, points. This is
+  //! an index in the triangles table specific to the triangulation
+  //! analyzed by this tool
+  Standard_Integer Value() const { return mytr; }
+
+private:
+
+  Handle(Poly_Triangulation) myTriangulation;
+  TColStd_Array1OfInteger myTriangles;
+  TColStd_Array1OfInteger myAdjacents;
+  Standard_Integer mytr;
+  Standard_Integer myfirst;
+  Standard_Integer mynode;
+  Standard_Integer myothernode;
+  Standard_Boolean mysense;
+  Standard_Boolean mymore;
+
+};
+
+//=======================================================================
+//function : Load
+//purpose  :
+//=======================================================================
+inline void Poly_Connect_Ex::Load (const Handle(Poly_Triangulation)& theTriangulation)
+{
+  myTriangulation = theTriangulation;
+  mytr = 0;
+  myfirst = 0;
+  mynode  = 0;
+  myothernode = 0;
+  mysense = false;
+  mymore  = false;
+
+  const Standard_Integer aNbNodes = myTriangulation->NbNodes();
+  const Standard_Integer aNbTris  = myTriangulation->NbTriangles();
+  {
+    const Standard_Integer aNbAdjs = 6 * aNbTris;
+    if (myTriangles.Size() != aNbNodes)
+    {
+      myTriangles.Resize (1, aNbNodes, Standard_False);
+    }
+    if (myAdjacents.Size() != aNbAdjs)
+    {
+      myAdjacents.Resize (1, aNbAdjs, Standard_False);
+    }
+  }
+
+  myTriangles.Init(0);
+  myAdjacents.Init(0);
+
+  // We first build an array of the list of edges connected to the nodes
+  // create an array to store the edges starting from the vertices
+  NCollection_Array1<polyedge*> anEdges (1, aNbNodes);
+  anEdges.Init (NULL);
+  // use incremental allocator for small allocations
+  Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator();
+
+  // loop on the triangles
+  NCollection_Vec3<Standard_Integer> aTriNodes;
+  NCollection_Vec2<Standard_Integer> anEdgeNodes;
+  for (Standard_Integer aTriIter = 1; aTriIter <= aNbTris; ++aTriIter)
+  {
+    // get the nodes
+    myTriangulation->Triangle (aTriIter).Get (aTriNodes[0], aTriNodes[1], aTriNodes[2]);
+
+    // Update the myTriangles array
+    myTriangles.SetValue (aTriNodes[0], aTriIter);
+    myTriangles.SetValue (aTriNodes[1], aTriIter);
+    myTriangles.SetValue (aTriNodes[2], aTriIter);
+
+    // update the edge lists
+    for (Standard_Integer aNodeInTri = 0; aNodeInTri < 3; ++aNodeInTri)
+    {
+      const Standard_Integer aNodeNext = (aNodeInTri + 1) % 3;  // the following node of the edge
+      if (aTriNodes[aNodeInTri] < aTriNodes[aNodeNext])
+      {
+        anEdgeNodes[0] = aTriNodes[aNodeInTri];
+        anEdgeNodes[1] = aTriNodes[aNodeNext];
+      }
+      else
+      {
+        anEdgeNodes[0] = aTriNodes[aNodeNext];
+        anEdgeNodes[1] = aTriNodes[aNodeInTri];
+      }
+
+      // edge from node 0 to node 1 with node 0 < node 1
+      // insert in the list of node 0
+      polyedge* ced = anEdges[anEdgeNodes[0]];
+      for (; ced != NULL; ced = ced->next)
+      {
+        // the edge already exists
+        if (ced->nd == anEdgeNodes[1])
+        {
+          // just mark the adjacency if found
+          ced->nt[1] = aTriIter;
+          ced->nn[1] = aTriNodes[3 - aNodeInTri - aNodeNext];  // the third node
+          break;
+        }
+      }
+
+      if (ced == NULL)
+      {
+        // create the edge if not found
+        ced = (polyedge* )anIncAlloc->Allocate (sizeof(polyedge));
+        ced->next = anEdges[anEdgeNodes[0]];
+        anEdges[anEdgeNodes[0]] = ced;
+        ced->nd = anEdgeNodes[1];
+        ced->nt[0] = aTriIter;
+        ced->nn[0] = aTriNodes[3 - aNodeInTri - aNodeNext];  // the third node
+        ced->nt[1] = 0;
+        ced->nn[1] = 0;
+      }
+    }
+  }
+
+  // now complete the myAdjacents array
+  Standard_Integer anAdjIndex = 1;
+  for (Standard_Integer aTriIter = 1; aTriIter <= aNbTris; ++aTriIter)
+  {
+    // get the nodes
+    myTriangulation->Triangle (aTriIter).Get (aTriNodes[0], aTriNodes[1], aTriNodes[2]);
+
+    // for each edge in triangle
+    for (Standard_Integer aNodeInTri = 0; aNodeInTri < 3; ++aNodeInTri)
+    {
+      const Standard_Integer aNodeNext = (aNodeInTri + 1) % 3;  // the following node of the edge
+      if (aTriNodes[aNodeInTri] < aTriNodes[aNodeNext])
+      {
+        anEdgeNodes[0] = aTriNodes[aNodeInTri];
+        anEdgeNodes[1] = aTriNodes[aNodeNext];
+      }
+      else
+      {
+        anEdgeNodes[0] = aTriNodes[aNodeNext];
+        anEdgeNodes[1] = aTriNodes[aNodeInTri];
+      }
+
+      // edge from node 0 to node 1 with node 0 < node 1
+      // find in the list of node 0
+      const polyedge* ced = anEdges[anEdgeNodes[0]];
+      while (ced->nd != anEdgeNodes[1])
+      {
+        ced = ced->next;
+      }
+
+      // Find the adjacent triangle
+      const Standard_Integer l = ced->nt[0] == aTriIter ? 1 : 0;
+
+      myAdjacents.SetValue (anAdjIndex,     ced->nt[l]);
+      myAdjacents.SetValue (anAdjIndex + 3, ced->nn[l]);
+      ++anAdjIndex;
+    }
+    anAdjIndex += 3;
+  }
+
+  // destroy the edges array - can be skipped when using NCollection_IncAllocator
+  for (Standard_Integer aNodeIter = anEdges.Lower(); aNodeIter <= anEdges.Upper(); ++aNodeIter)
+  {
+    for (polyedge* anEdgeIter = anEdges[aNodeIter]; anEdgeIter != NULL;)
+    {
+      polyedge* aTmp = anEdgeIter->next;
+      anIncAlloc->Free (anEdgeIter);
+      anEdgeIter = aTmp;
+    }
+  }
+}
+
+//=======================================================================
+//function : Initialize
+//purpose  : 
+//=======================================================================
+
+inline void Poly_Connect_Ex::Initialize(const Standard_Integer N)
+{
+  mynode = N;
+  myfirst = Triangle(N);
+  mytr = myfirst;
+  mysense = Standard_True;
+  mymore = (myfirst != 0);
+  if (mymore)
+  {
+    Standard_Integer i, no[3];
+    //const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();
+	const Poly_Array1OfTriangle& triangles = POLY_TRIGULATION_TRIANGLES(myTriangulation);
+    triangles(myfirst).Get(no[0], no[1], no[2]);
+    for (i = 0; i < 3; i++)
+      if (no[i] == mynode) break;
+    myothernode = no[(i+2)%3];
+  }
+}
+
+//=======================================================================
+//function : Next
+//purpose  : 
+//=======================================================================
+
+inline void Poly_Connect_Ex::Next()
+{
+  Standard_Integer i, j;
+  Standard_Integer n[3];
+  Standard_Integer t[3];
+  //const Poly_Array1OfTriangle& triangles = myTriangulation->Triangles();
+  const Poly_Array1OfTriangle& triangles = POLY_TRIGULATION_TRIANGLES(myTriangulation);
+  Triangles(mytr, t[0], t[1], t[2]);
+  if (mysense) {
+    for (i = 0; i < 3; i++) {
+      if (t[i] != 0) {
+	triangles(t[i]).Get(n[0], n[1], n[2]);
+	for (j = 0; j < 3; j++) {
+	  if ((n[j] == mynode) && (n[(j+1)%3] == myothernode)) {
+	    mytr = t[i];
+	    myothernode = n[(j+2)%3];
+	    mymore = (mytr != myfirst);
+	    return;
+	  }
+	}
+      }
+    }
+    // sinon, depart vers la gauche.
+    triangles(myfirst).Get(n[0], n[1], n[2]);
+    for (i = 0; i < 3; i++)
+      if (n[i] == mynode) break;
+    myothernode = n[(i+1)%3];
+    mysense = Standard_False;
+    mytr = myfirst;
+    Triangles(mytr, t[0], t[1], t[2]);
+  }
+  if (!mysense) {
+    for (i = 0; i < 3; i++) {
+      if (t[i] != 0) {
+	triangles(t[i]).Get(n[0], n[1], n[2]);
+	for (j = 0; j < 3; j++) {
+	  if ((n[j] == mynode) && (n[(j+2)%3] == myothernode)) {
+	    mytr = t[i];
+	    myothernode = n[(j+1)%3];
+	    mymore = Standard_True;
+	    return;
+	  }
+	}
+      }
+    }
+  }
+  mymore = Standard_False;
+}
+
+
+
+#endif // _Poly_Connect_HeaderFile

+ 66 - 0
comx_sdk.node/js/_model.js

@@ -2594,6 +2594,72 @@ exports.saveFormDBToKul         = saveFormDBToKul;
 ////////////////////////////////////////////////////////////////////////
 // Execute Form or Open a new Frame.
 
+var g_debug_process = false;
+function debugUnit(unit_name, geo, cb, ready)
+{
+    if(!g_debug_process)
+    {
+        var cmd      = path.join(unit.dir,'utils','debug.js');
+        var entry_js = path.join(unit.dirUnit(unit_name), '_entry.js');
+
+        let margin_x = 120;
+        let margin_y = 40;
+        g_debug_process = fork(cmd,
+                               [entry_js,
+                                geo.x + margin_x * 2,
+                                geo.y + margin_y,
+                                geo.width - 2 * margin_x - margin_y,
+                                geo.height - 2 * margin_y
+                               ],
+                               { silent: true });
+
+        g_debug_process.on('exit', ()=>{
+            g_debug_process = false;
+            if(cb) cb();
+        });
+
+        g_debug_process.on('message', msg=>{
+            if(ready)ready();
+        });
+        
+        try{
+            g_debug_process.stdout.on('data', (data)=>{
+	        unit.form.kul_editor.outputInfo('<span style="color:red">' + data + '</span>');
+	        outputGlobalLogInfo(data); 
+	    });
+            
+	    g_debug_process.stderr.on('data', (data)=>{
+	        unit.form.kul_editor.outputInfo('<span style="color:red">' + data + '</span>');
+	        outputGlobalLogInfo(data); 
+	    });
+        }
+        catch(err)
+        {
+            console.log(err);
+        }
+    }
+}
+
+exports.debugUnit = debugUnit;
+
+function stopDebugUnit()
+{
+    try
+    {
+        if(g_debug_process)
+        {
+            g_debug_process.kill();
+            g_debug_process = false;
+        }
+    }
+    catch(err)
+    {
+        console.log(err);
+    }
+}
+
+exports.stopDebugUnit = stopDebugUnit;
+
 function executeUnit(unit_name, form_name)
 {
     updateUnitEntry(unit_name);

+ 24 - 2
comx_sdk.node/js/dev.js

@@ -1,3 +1,25 @@
+global.__comx_global_exception_function = function(e, promise){
+    if(promise) {
+        console.log('unhandledRejection:', e, promise);
+    }
+    else {
+//        if(e && e.message) {
+//            console.log('uncaughtException:', e.message);
+//        }
+//        else {
+            console.log('uncaughtException:', e);
+//        }
+    }
+};
+
+process.on('uncaughtException', (e)=>{
+    __comx_global_exception_function(e);
+});
+
+process.on('unhandledRejection',function(err,promise){
+    __comx_global_exception_function(err, promise);
+});
+
 var fs = require('fs');
 var vm = require('vm');
 const { execSync } = require('child_process');
@@ -75,7 +97,7 @@ else
 process.on('uncaughtException', (e)=>{
     console.error('process error is:', e.message);
 });
-*/
+
 
 process.on('uncaughtException', (err, origin) => {
 
@@ -92,7 +114,7 @@ process.on('uncaughtException', (err, origin) => {
         console.log(err);
     }
 });
-
+*/
 /////////////////////////////////////////////////////////////////////////////
 // Init Runtime Env
 

+ 27 - 0
comx_sdk.node/js/kul_editor_pane.js

@@ -1251,6 +1251,33 @@ function OnExecute()
 	model.executeUnit(ui.units.value, 'mainfrm');
 }
 
+function OnDebug()
+{
+    let geo = ui.GetWidgetGeometry(ui.callback.handle);
+    ui.pb_preview.valid = false;
+    OnPreview(false);
+
+    setCuelineInfo('<span style="color:darkblue">Starting debugger, please wait a moment ...</span>');
+    parent.setTimeout(()=>{
+        setCuelineInfo('Ready.'); 
+    }, 15000);
+    
+    ui.debug_btn.visible = false;
+    ui.stop_debug_btn.visible = true;
+    model.debugUnit(ui.units.value, geo, ()=>{
+        ui.debug_btn.visible = true;
+        ui.stop_debug_btn.visible = false;
+        setCuelineInfo('Ready.'); 
+    },()=>{
+        setCuelineInfo('Ready.'); 
+    });
+}
+
+function OnStopDebug()
+{
+    model.stopDebugUnit(ui.units.value);
+}
+
 function OnFrame()
 {
     model.executeUnit('comx_sdk', 'kul_editor');

+ 1 - 0
comx_sdk.node/js/workArea.cfg.json

@@ -0,0 +1 @@
+{}

+ 61 - 5
comx_sdk.node/kul/toolbarpane_new.kul

@@ -214,11 +214,11 @@
               <property name="scroll_steps">3</property>
               <widget type="pushbutton">
                 <property name="name">pbn_execute</property>
-                <property name="label">_Execute</property>
-                <property name="tip">Run current unit.</property>
-                <property name="bitmap">play</property>
+                <property name="label"/>
+                <property name="tip">Run current unit without debug.</property>
+                <property name="bitmap">play_without_debug.bmp</property>
                 <property name="bitmap_align">left</property>
-                <property name="width">40</property>
+                <property name="width">13</property>
                 <property name="height">12</property>
                 <property name="adjust">fixed</property>
                 <property name="can_check">false</property>
@@ -240,6 +240,62 @@
                 <property name="hightlight">false</property>
                 <property name="stylesheet"/>
               </widget>
+              <widget type="pushbutton">
+                <property name="name">debug_btn</property>
+                <property name="label"/>
+                <property name="tip">Run current unit with debug.</property>
+                <property name="bitmap">play.bmp</property>
+                <property name="bitmap_align">left</property>
+                <property name="width">13</property>
+                <property name="height">12</property>
+                <property name="adjust">fixed</property>
+                <property name="can_check">false</property>
+                <property name="default">false</property>
+                <property name="flat">true</property>
+                <property name="flat_radio">false</property>
+                <property name="gray">false</property>
+                <property name="id_alias">nil</property>
+                <property name="visible">true</property>
+                <property name="onClick">OnDebug();</property>
+                <property name="onContentMenu"/>
+                <property name="shadow">false</property>
+                <property name="shadow_type">soft</property>
+                <property name="enable_bind"/>
+                <property name="simple_bind"/>
+                <property name="valid_bind"/>
+                <property name="visible_bind"/>
+                <property name="handle_bind"/>
+                <property name="hightlight">false</property>
+                <property name="stylesheet"/>
+              </widget>
+              <widget type="pushbutton">
+                <property name="name">stop_debug_btn</property>
+                <property name="label"/>
+                <property name="tip">Stop current debugging process.</property>
+                <property name="bitmap">stop.bmp</property>
+                <property name="bitmap_align">left</property>
+                <property name="width">13</property>
+                <property name="height">12</property>
+                <property name="adjust">fixed</property>
+                <property name="can_check">false</property>
+                <property name="default">false</property>
+                <property name="flat">true</property>
+                <property name="flat_radio">false</property>
+                <property name="gray">false</property>
+                <property name="id_alias">nil</property>
+                <property name="visible">false</property>
+                <property name="onClick">OnStopDebug();</property>
+                <property name="onContentMenu"/>
+                <property name="shadow">false</property>
+                <property name="shadow_type">soft</property>
+                <property name="enable_bind"/>
+                <property name="simple_bind"/>
+                <property name="valid_bind"/>
+                <property name="visible_bind"/>
+                <property name="handle_bind"/>
+                <property name="hightlight">false</property>
+                <property name="stylesheet"/>
+              </widget>
               <widget type="pushbutton">
                 <property name="name">pb_preview</property>
                 <property name="label">_Preview</property>
@@ -274,7 +330,7 @@
               <property name="data">Current Pane, MainWindow, Browser Mode</property>
               <property name="tip"/>
               <property name="id_alias">33</property>
-              <property name="width">81</property>
+              <property name="width">67</property>
               <property name="height">12</property>
               <property name="adjust">fixed</property>
               <property name="flat">true</property>

+ 12 - 0
comx_sdk.node/node_modules/.bin/browsers

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../@puppeteer/browsers/lib/cjs/main-cli.js" "$@"
+else 
+  exec node  "$basedir/../@puppeteer/browsers/lib/cjs/main-cli.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/browsers.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\@puppeteer\browsers\lib\cjs\main-cli.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/browsers.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../@puppeteer/browsers/lib/cjs/main-cli.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../@puppeteer/browsers/lib/cjs/main-cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../@puppeteer/browsers/lib/cjs/main-cli.js" $args
+  } else {
+    & "node$exe"  "$basedir/../@puppeteer/browsers/lib/cjs/main-cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/browserslist

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../browserslist/cli.js" "$@"
+else 
+  exec node  "$basedir/../browserslist/cli.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/browserslist.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\browserslist\cli.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/browserslist.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../browserslist/cli.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../browserslist/cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../browserslist/cli.js" $args
+  } else {
+    & "node$exe"  "$basedir/../browserslist/cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/escodegen

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../escodegen/bin/escodegen.js" "$@"
+else 
+  exec node  "$basedir/../escodegen/bin/escodegen.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/escodegen.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\escodegen\bin\escodegen.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/escodegen.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../escodegen/bin/escodegen.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../escodegen/bin/escodegen.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../escodegen/bin/escodegen.js" $args
+  } else {
+    & "node$exe"  "$basedir/../escodegen/bin/escodegen.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/esgenerate

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../escodegen/bin/esgenerate.js" "$@"
+else 
+  exec node  "$basedir/../escodegen/bin/esgenerate.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/esgenerate.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\escodegen\bin\esgenerate.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/esgenerate.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../escodegen/bin/esgenerate.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../escodegen/bin/esgenerate.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../escodegen/bin/esgenerate.js" $args
+  } else {
+    & "node$exe"  "$basedir/../escodegen/bin/esgenerate.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/esparse

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../esprima/bin/esparse.js" "$@"
+else 
+  exec node  "$basedir/../esprima/bin/esparse.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/esparse.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\esprima\bin\esparse.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/esparse.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  } else {
+    & "node$exe"  "$basedir/../esprima/bin/esparse.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/esvalidate

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../esprima/bin/esvalidate.js" "$@"
+else 
+  exec node  "$basedir/../esprima/bin/esvalidate.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/esvalidate.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\esprima\bin\esvalidate.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/esvalidate.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  } else {
+    & "node$exe"  "$basedir/../esprima/bin/esvalidate.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/extract-zip

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../extract-zip/cli.js" "$@"
+else 
+  exec node  "$basedir/../extract-zip/cli.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/extract-zip.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\extract-zip\cli.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/extract-zip.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../extract-zip/cli.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../extract-zip/cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../extract-zip/cli.js" $args
+  } else {
+    & "node$exe"  "$basedir/../extract-zip/cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/import-local-fixture

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../import-local/fixtures/cli.js" "$@"
+else 
+  exec node  "$basedir/../import-local/fixtures/cli.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/import-local-fixture.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\import-local\fixtures\cli.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/import-local-fixture.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../import-local/fixtures/cli.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../import-local/fixtures/cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../import-local/fixtures/cli.js" $args
+  } else {
+    & "node$exe"  "$basedir/../import-local/fixtures/cli.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/jest

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../jest/bin/jest.js" "$@"
+else 
+  exec node  "$basedir/../jest/bin/jest.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/jest.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\jest\bin\jest.js" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/jest.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../jest/bin/jest.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../jest/bin/jest.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../jest/bin/jest.js" $args
+  } else {
+    & "node$exe"  "$basedir/../jest/bin/jest.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/jsesc

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../jsesc/bin/jsesc" "$@"
+else 
+  exec node  "$basedir/../jsesc/bin/jsesc" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/jsesc.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\jsesc\bin\jsesc" %*

+ 28 - 0
comx_sdk.node/node_modules/.bin/jsesc.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../jsesc/bin/jsesc" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../jsesc/bin/jsesc" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../jsesc/bin/jsesc" $args
+  } else {
+    & "node$exe"  "$basedir/../jsesc/bin/jsesc" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 12 - 0
comx_sdk.node/node_modules/.bin/json5

@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../json5/lib/cli.js" "$@"
+else 
+  exec node  "$basedir/../json5/lib/cli.js" "$@"
+fi

+ 17 - 0
comx_sdk.node/node_modules/.bin/json5.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\json5\lib\cli.js" %*

+ 0 - 0
comx_sdk.node/node_modules/.bin/json5.ps1


Some files were not shown because too many files changed in this diff