Bentley Communities
Bentley Communities
  • Site
  • User
  • Site
  • Search
  • User
  • Welcome
  • Products
  • Support
  • About
  • More
  • Cancel
中国BDN社区
  • Welcome to Bentley Communities
  • Bentley's Communities
  • 中国BDN社区
  • Cancel
中国BDN社区
中国BDN社区-威客 iModel文件的合并等操作
    • Sign In
    • 中国BDN社区-威客
    • -iTwin.js编程
      • iModel.js Front-End简介
      • iModel.js 样例项目配置与运行
      • iModel.js.UI开发基本介绍
      • iModel.js前端统一选择一致性机制
      • iModel.js基本查询
      • iModel.js若干前端功能开发样例
      • imodel图形显示简单介绍
      • iModel文件的合并等操作
      • Redux基本使用
      • simple-viewer-app源码简单分析
      • TypeScript基本介绍及环境配置
      • 下载视口截图
      • 关于imodel测量单位的转换
      • 关于如何导入与导出imodel中schema文件
      • 基于PresentationRules个性化显示iModel的内容
      • 如何在视窗内添加自定义装饰
      • 如何将2个bim中的图形模型显示在一个视图中
      • 用户选择保存感兴趣的视图
    • +MicroStation CONNECT版SDK的新变化
    • +MicroStation编程技巧
    • +OpenRoads中国版平台开发指南
    • +ORD SDK二次开发编程
    • +一步步学习ABD-CE开发
    • +一步步学习MicroStation CE Addin开发
    • 一步步学习MicroStation CE MDL开发
    • +一步步学习ProjectWise编程
    • 中国优先社区二次开发精华帖汇总
    • +学习Microstation交互式工具开发
    • +过期帖,留存仅供参考
    • +非Bentley社区分享的文章
    • C#、C/C++相关的编程知识汇总

     
     Questions about this article, topic, or product? Click here. 

    iModel文件的合并等操作

    合并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中,并可以成功显示出来。

    • Share
    • History
    • More
    • Cancel
    • Devin Liu Created by Devin Liu
    • When: Tue, Aug 25 2020 3:15 AM
    • Devin Liu Last revision by Devin Liu
    • When: Tue, Aug 25 2020 4:37 AM
    • Revisions: 6
    • Comments: 0
    Recommended
    Related
    Communities
    • Home
    • Getting Started
    • Community Central
    • Products
    • Support
    • Secure File Upload
    • Feedback
    Support and Services
    • Home
    • Product Support
    • Downloads
    • Subscription Services Portal
    Training and Learning
    • Home
    • About Bentley Institute
    • My Learning History
    • Reference Books
    Social Media
    •    LinkedIn
    •    Facebook
    •    Twitter
    •    YouTube
    •    RSS Feed
    •    Email

    © 2023 Bentley Systems, Incorporated  |  Contact Us  |  Privacy |  Terms of Use  |  Cookies