合并imodel文件专题
IModelImporter
用于将数据导入iModel的基类,用户可以根据需要重写子类。
示例代码如下所示:
//用户自定义基类,重写若干基类函数,以实现自己的需求。 class MyIModelImporter extends IModelImporter { public constructor(targetDb: IModelDb, options?: IModelImportOptions) { super(targetDb, options); } //重写基类函数,当插入一个模型的时候被调用; protected onInsertModel(modelProps: ModelProps): Id64String { console.log("添加了一个model"); return super.onInsertModel(modelProps); } //重写基类函数,当插入一个元素的时候被调用; protected onInsertElement(elementProps: ElementProps): Id64String { console.log("添加了一个元素,其class=" + elementProps.classFullName); return super.onInsertElement(elementProps); } //重写基类函数,当删除一个元素的时候被调用; protected onDeleteElement(elementId: Id64String): void { console.log("删除的元素的id为:" + elementId); super.onDeleteElement(elementId); } } export async function IModelTransformer_IModelImporter() { //首先创建一个测试imodel文件,因为使用openFile打开是只读的。 //所以,我们通过createFrom基于种子imodel文件创建一个可读可写的iMode文件。 const seedFileName = "./data3/CompatibilityTestSeed.bim"; const seedDb = SnapshotDb.openFile(seedFileName); const sourceFileName = "./data3/TargetIModel.bim"; if (IModelJsFs.existsSync(sourceFileName)) { IModelJsFs.removeSync(sourceFileName); } //注意,我们所创建的imodel文件设置了密码为'abcdef123456'. let TargetIModel = SnapshotDb.createFrom(seedDb, sourceFileName, { password: "abcdef123456", }); //创建成功之后,即可关闭种子文件。 seedDb.close(); //检测一下,新创建的imodel文件是否可读可写。 if (TargetIModel.isReadonly) { console.log("只读"); } else { console.log("可读可写"); } //创建一个MyIModelImporter实例,然后进行一下操作: const MyImporter = new MyIModelImporter(TargetIModel); const subjectId = TargetIModel.elements.getRootSubject().id; //创建两个建模元素分区属性; const partitionProps: InformationPartitionElementProps = { classFullName: DefinitionPartition.classFullName, model: IModel.repositoryModelId, parent: new SubjectOwnsPartitionElements(subjectId), code: DefinitionPartition.createCode(TargetIModel, subjectId, "AddModel"), }; const partitionProps2: InformationPartitionElementProps = { classFullName: DefinitionPartition.classFullName, model: IModel.repositoryModelId, parent: new SubjectOwnsPartitionElements(subjectId), code: DefinitionPartition.createCode(TargetIModel, subjectId, "TestRemove"), }; //先导入2个建模元素; const partitionId = MyImporter.importElement(partitionProps); const partitionId2 = MyImporter.importElement(partitionProps2); //创建一个DefinitionModel属性,注意其建模元素id是之前所插入的建模元素id。 const modelProps: ModelProps = { classFullName: DefinitionModel.classFullName, modeledElement: { id: partitionId }, id: partitionId, name: "TestModel", }; MyImporter.importModel(modelProps); //删除id为partitionId2的建模元素。 MyImporter.deleteElement(partitionId2); TargetIModel.close(); //测试所插入的模型是否存在。 const testDb = SnapshotDb.openFile(sourceFileName, { password: "abcdef123456", }); const modelP = testDb.models.tryGetModelProps(partitionId); if (modelP) { console.log("测试成功"); console.log( "name = " + modelProps.name + "classfullName = " + modelProps.classFullName ); } }
运行结果如下所示:
使用IModelTransformer基本导入
基本操作:将一个imodel中的内容全部导入到另一个imodel中。
示例代码如下所示:
export async function IModelTransformer_Handle() { //打开源imodel文件作为源; const SourceFileName = "./data3/CompatibilityTestSeed.bim"; const SourceIModel = SnapshotDb.openFile(SourceFileName); //计算源imodel中元素个数; const ElementNumOfSource = count(SourceIModel, Element.classFullName); console.log("源 element 个数=" + ElementNumOfSource.toString()); //输出62 //创建一个空imodel文件作为目标; const targetFileName = "./data3/TestTargetiModel.bim"; if (IModelJsFs.existsSync(targetFileName)) { IModelJsFs.removeSync(targetFileName); } const targetDbProps: CreateIModelProps = { rootSubject: { name: "Clone-Target" }, ecefLocation: SourceIModel.ecefLocation, }; const targetDb = SnapshotDb.createEmpty(targetFileName, targetDbProps); //计算导入之前目的imodel中元素个数; const importBeforeNum = count(targetDb, Element.classFullName); console.log("import before number = " + importBeforeNum); //输出3 const transformer = new IModelTransformer(SourceIModel, targetDb); await transformer.processSchemas(new BackendRequestContext()); //导入全部; transformer.processAll(); transformer.dispose(); //计算导入之后目的imodel中元素个数; const afterBeforeNum = count(targetDb, Element.classFullName); console.log("import after number = " + afterBeforeNum); //输出62 SourceIModel.close(); targetDb.close(); }
使用IModelTransformer根据指定规则导入
将一个imodel中的内容,按照预先设定的规则将其内容导入到另一个imodel中。
示例代码如下所示:
export async function IModelTransformer_Handle() { //打开源imodel文件作为源; const SourceFileName = "./data3/CompatibilityTestSeed.bim"; const SourceIModel = SnapshotDb.openFile(SourceFileName); //计算源imodel中元素个数; const ElementNumOfSource = count(SourceIModel, Element.classFullName); console.log("源 element 个数=" + ElementNumOfSource.toString()); //输出62 //创建一个空imodel文件作为目标; const targetFileName = "./data3/TestTargetiModel.bim"; if (IModelJsFs.existsSync(targetFileName)) { IModelJsFs.removeSync(targetFileName); } const targetDbProps: CreateIModelProps = { rootSubject: { name: "Clone-Target" }, ecefLocation: SourceIModel.ecefLocation, }; const targetDb = SnapshotDb.createEmpty(targetFileName, targetDbProps); //计算导入之前目的imodel中元素个数; const importBeforeNum = count(targetDb, Element.classFullName); console.log("import before number = " + importBeforeNum); //输出3 // IModelExporter const expor = new IModelExporter(SourceIModel); // 统计DrawingGraphic的实例个数; const drawElementNumber = count(SourceIModel, DrawingGraphic.classFullName); console.log("DrawElementNumber = " + drawElementNumber.toString()); // 输出18; // 将DrawingGraphic的所有实例排除,也就是不导入到目标imodel中; expor.excludeElementClass(DrawingGraphic.classFullName); //IModelImporter const impor = new IModelImporter(targetDb); const transformer = new IModelTransformer(expor, impor); await transformer.processSchemas(new BackendRequestContext()); //导入全部; transformer.processAll(); transformer.dispose(); //计算导入之后目的imodel中元素个数; const afterBeforeNum = count(targetDb, Element.classFullName); console.log("import after number = " + afterBeforeNum); //输出44,其中18个DrawingGraphic的实例没有导入。 SourceIModel.close(); targetDb.close(); } function count(iModelDb: IModelDb, classFullName: string): number { return iModelDb.withPreparedStatement( `SELECT COUNT(*) FROM ${classFullName}`, (statement: ECSqlStatement): number => { return DbResult.BE_SQLITE_ROW === statement.step() ? statement.getValue(0).getInteger() : 0; } ); }
将两个imodel同时导入到另一个imodel中
现有2个imodel分别为A,B,欲将A,B导入到另一个imodel C中,需要首先在C中建立2个分区,然后将A,B imodel分别导入到不同的分区中。
示例代码如下所示:
export async function IModelTransformer_Handle2() { const SourceFileName1 = "./data2/Baytown.bim"; const sourceFileName2 = "./data2/house.bim"; const SrouceModel1 = SnapshotDb.openFile(SourceFileName1); const SrouceModel2 = SnapshotDb.openFile(sourceFileName2); //导入之前,分别计算2个源imodel中element的个数并打印; const num1 = count(SrouceModel1, Element.classFullName); const num2 = count(SrouceModel2, Element.classFullName); console.log("num1 = " + num1.toString()); //输出4962 console.log("num2 = " + num2.toString()); //输出3169 //创建一个新的imodel作为目标imodel,然后将2个源imodel导入到目标imodel中; const targetFileName = "./data2/TestTargetiModel.bim"; if (IModelJsFs.existsSync(targetFileName)) { IModelJsFs.removeSync(targetFileName); } const targetDbProps: CreateIModelProps = { rootSubject: { name: "Clone-Target" }, }; const targetDb = SnapshotDb.createEmpty(targetFileName, targetDbProps); //在目标imodel中targetDb中创建2个分区,分别容纳2个源imodel; const parentSubject = targetDb.elements.getRootSubject().id; const subjectId1 = Subject.insert(targetDb, parentSubject, "subject1"); const subjectId2 = Subject.insert(targetDb, parentSubject, "subject2"); const rc = new BackendRequestContext(); //注意在导入的时候,如果提示 UnhandledPromiseRejectionWarning: Schema Upgrade Failed: Error importing schema //可以尝试改变导入的imodel的顺序,这也就是为什么这里先导入2,再导入1的原因。 //开始创建导入transformer2; const transformer2 = new IModelTransformer(SrouceModel2, targetDb, { targetScopeElementId: subjectId2, }); await transformer2.processSchemas(rc); //导入全部; transformer2.processAll(); transformer2.dispose(); //开始创建导入transformer1; const transformer1 = new IModelTransformer(SrouceModel1, targetDb, { targetScopeElementId: subjectId1, }); await transformer1.processSchemas(rc); //导入全部; transformer1.processAll(); transformer1.dispose(); //计算导入后目标imodel中element的个数 const num = count(targetDb, Element.classFullName); console.log("num = " + num.toString()); //输出8128 SrouceModel1.close(); SrouceModel2.close(); targetDb.close(); }
导入之前A,B imodel显示图分别为:
导入之后C imodel显示如下所示:
通过对比右边显示的View列表,我们即可发现已经将A,B imodel成功导入了C imodel中,并可以成功显示出来。