# MBI流程
    上传
    操作：revit点击 上传按钮
    
     模型文件版本检查；
       检查模型文件版本是否过期
    加锁检查
    1，获取所有楼层（F1~F20）
    2，过滤出更改楼层(计算本地模型文件的Md5值与FileVision.json中本层的Md5值对比，如果不一致表明文件发生更改)
    3，过滤出加锁的楼层（本人加锁才可以提交）
    
    显示 上传模型管理窗口 
![uploader](./img/mbi_001.png)
    
    点击确定上传按钮
    
    1，模型与物理世界 信息点同步
    设备本地编码、设备本地名称、空间本地名称 Revit文件赋值
    取物理世界信息点的值，覆盖Revit文件中信息点的值。
    2，获取需要增加、删除、修改的岗位数据
    3，获取基本关系（设备所在元空间、信标所在元空间）更改。
    缓存物理世界岗位数据serviceContext:dutys（设备、部件、信标、元空间）；
    由Revit模型文件计算需要上传的岗位数据localContext:localDutys（设备、部件、信标、元空间）+基本关系；
    
    岗位数据和基本关系数据整理逻辑
    输入：物理世界数据缓存serviceContext,本地模型计算计算localContext
    输出：岗位和基本关系标记（add,del,modify,none）设置正确,准备上传
    流程：
    遍历localDutys:localDuty
      由localDuty的bimid，去dutys集合中查找,赋值给tempDutys;  
      判断tempDutys集合个数；  
        等于零；从本地数据库，由Bimd获
        取dutyId,(待建模型清单产生)，跟据dutyId去dutys集合中查找，赋值给tempDutys。
      再次判断tempDutys集合个数：
        等于零，说明没有找到物理世界对应的数据；
        ，此localDuty数据标记为add    
          处理基本关系    
        等于1，取第一个duty    
        大于1，多个岗位共用一个BIMID  ,tempDutys按信息点的个数从大到小排序，取第一个duty，其它标记为Delete    
        duty.Id赋值给localDuty.Id    
        判断localDuty.code与duty.code是否相等    
        不相等，表示族编码发生更改    
          删除物理世界旧岗位duty标记为del，创建本地新岗位localDuty标记为add,    
        相等    
          物理世界旧岗位标duty记为Modify,本地岗位localDuty标记为Modify    
         处理基本关系    
    遍历dutys:duty
    判断duty的状态
    等于del
    等于none
      duty标记为del
      删除物理世界的相应的基本关系
    等于modify或者duty中的BIMId格式不正确（待建模清单中的岗位）
      duty标记为none
    
    
    处理基本关系
    输入：模型计算结果localContext,岗位localDuty
    输出：localContext基本关系，标记设置正确
    流程：
    判断localDuty类型：
    空间：
       更新设备所在元空间、信标所在元空间关系
        依据元空间BIMID从原始集合equipInSpaceRelations，beaconInSpaceRelations中找到关联的关系集合，tempEquipRelations,tempBeaconRelations
        判断空间状态
        add:tempRelations集合状态设置为add
        del:tempRelations集合状态设置为del
        Modified:关系删除后增加，tempEquipRelations,tempBeaconRelations集合状态设置为del,复制集合添加至原始集合中标记为add   
    信标：
      更新信标所在元空间关系
         依据信标BIMID从原始集合beaconInSpaceRelations中找到关联的关系集合，tempRelations
        判断信标状态
        add:tempRelations集合状态设置为add
        del:tempRelations集合状态设置为del
        Modified:关系删除后增加，tempRelations集合状态设置为del,复制集合添加至原始集合中标记为add
    设备：
      更新设备所在元空间关系
        依据设备BIMID从原始集合equipInSpaceRelations中找到关联的关系集合，tempRelations
        判断空间状态
        add:tempRelations集合状态设置为add
        del:tempRelations集合状态设置为del
        Modified:关系删除后增加，tempRelations集合状态设置为del,复制集合添加至原始集合中标记为add   
    
    
    得到增加，删除，修改的数据（BIMLocation）。
    删除物理世界的相应的基本关系
    输入：物理世界数据缓存serviceContext,岗位duty
    输出：serviceContext基本关系，标记设置正确
    流程：
    判断duty类型
    空间：
    依据空间，新建关系，设备所在元空间equipInSpace，信标所在元空间beaconInSpace,标记为del
    将新建的数据添加到集合equipInSpaceRelations，beaconInSpaceRelations
    信标：
    依据信标，新建关系，信标所在元空间beaconInSpace,标记为del
    将新建的数据添加到集合beaconInSpaceRelations
    设备、部件：
    依据设备，新建关系，设备所在元空间equipInSpace，标记为del
    将新建的数据添加到集合equipInSpaceRelations
    
    由增加岗位集合，获取增加的基本关系
    由删除的岗位集合，获取删除的基本关系
    由修改的岗位集合，先删除，后增加
    4，与物理世界交互，依据2同步岗位，依据3同步基本关系
    
    输入：
    物理世界项目-建筑-楼层树结构+岗位数据+Revit模型文件
    输出：
    待同步的岗位数据+基本关系数据
    
    上传Revit模型
    
    解锁
    
    删除日志文件，删除Revit备份文件
    
    上传底图数据（柱子，墙，元空间，设备、虚拟墙）现在没有门窗，想要门窗
    
    关闭 上传模型管理窗体
    
    空间管理
    操作：Revit点击：空间管理按钮
    获取 项目-建筑-楼层 树结构
    初始化绘图区域
    显示 空间管理 窗体
![uploader](./img/mbi_002.png)

    点击 楼层（F1Test）
    检测是否有未保存的数据，数据分两部分：新建的空间分隔符，删除的空间分隔符
    弹出提示信息 “尚未保存空间变化，确认放弃修改?”
    执行初始化楼层
    查找以-saga结尾的平面视图。如果不存在弹出提示信息“无法找到名称以-saga结尾的视图！”
    加载Revit模型数据（墙，虚拟墙，柱子,建筑柱，结构柱）
    创建空间
    将空间分隔符转化为房间分隔符
    获取封闭区域（doc.get_PlanTopology(level, phase);）topologyCircuit
    回滚创建房间分隔符操作
    由封闭区域topologyCircuit，获取内部点
    在指定点创建空间（doc.Create.NewSpace(level, phase, new UV(point.X, point.Y));）
    处理冲突空间
    绘制墙，虚拟墙，柱，空间
    
    点击 绘制虚拟墙
    开始绘制
    状态切换为 正在绘制状态
    鼠标状态切换为 手形
    
    再次点击绘制虚拟墙
    结束绘制
    状态切换为 结束绘制状态
    鼠标状态切换为 鼠标
    
    鼠标左键单击 画布
    绘制
    如果为首个点，点击点向已有线做投影，记录投影点，添加到Polyline集合
    如果不为首个点，记录点击点，添加到Polyline集合中
    
    鼠标右键单击 画布
    结束绘制
    如果为首个点，取消绘制
    如果不为首个点，点击点向已有线做投影，记录投影点，添加到Polyline集合
    
    鼠标点击 保存并更改模型
    保存模型
    依据新增和删除线集合，删除和创建空间
    删除空间
    有删除线的集合，从原空间分隔符集合中，查找到对应的空间分隔符Revit-id，删除空间分隔符
    由新增集合，创建空间分隔符。
    创建空间
    将空间分隔符转化为房间分隔符
    获取封闭区域（doc.get_PlanTopology(level, phase);）topologyCircuit
    回滚创建房间分隔符操作
    由封闭区域topologyCircuit，获取内部点
    在指定点创建空间（doc.Create.NewSpace(level, phase, new UV(point.X, point.Y));）
    处理冲突空间
    冲突处理逻辑：
    输入：冲突的空间Revit Id （多个）,localDutys
    输出：得到需要保留的空间Id,删除需要舍弃的空间
    流程：
    分别由Revit Id 获取物理世界对应dutyId（多个）
    判断localDutys集合
    如果获取的dutyId数量等于大于一，弹出提示框，让用户选择保存那一个空间，删除其它空间。
    如果获取的dutyId数量等于一，保留此空间，删除其它空间
    如果获取的dutyId数量等于0，保留RevitId最小的空间，删除其它空间。
    
    输入：
    修改的线集合+Revit模型
    输出：
    Revit模型中创建虚拟墙和空间
    
    保存模型
    提示用户上传模型
    
    
    
    
    空间拓扑计算-平面
    1，判断空间计算数据的状态
    Miss 缺失 重新计算
    Expire 过期 提示用户选择是否重新计算
    2，重新计算
    1，  获取所有的楼层文件
    2，  缓存楼层下的Doors,Windows,Spaces→ ComputerSpaceItems: ComputerSpaceItem
    3，  Parse 
    a)         Spaces→Context. M_SaveSpaces: SgSpace空间计算结果数据结构
    b)        CurrentFloorParse 平面解析
    空间转为空间边构件数据结构 Spaces→ flatSpaceItems :SpaceEdgeInfo 
    依据构件Id进行，flatSpaceItems .groupBy(t.EdgeElement.Id) 
     合并分组，平行且间距小于两个厚度之和的一半的构件看成一个构件关系relations
    判断同一分组共用构件的边类型，判断邻接构件是否为虚拟墙，如果是墙是否包含门、窗。
    形成空间两两的邻接关系，以及邻接构件 spaceRelations
             整理，将两两关系，转化为一个与其它空间的关系，Dictionary<string, SgSpace>
    c)         UpFloorParse 立面解析
    从上到下获取相邻的楼层，两两对比 floorUp和floorDown
    将floorUp和floorDown的空间投影到一个平面，计算两个平面空间的重叠关系。
    算法：
    1.         将凹多边形（至少有一个内角大于180度）拆分成多个凸多边形（内角小于等于180度）
    拆分凹角
    a)         取得空间点集合外圈逆时针，内圈顺时针。
    b)        取Y值最小的点，如果多个，取X值最小的点 做为起点start
    c)         逆时针取第二个点为end
    d)        取第三个点point，判断start-end,与point-end点乘是否大于零
    大于零 end点的内角 角度小于180 以end做为start继续计算
    小于零 end点的内角 角度大于180 将point 做为end点继续向后计算，如果计算结果大于零，连接start point,形成拆分线
    等于零 夹角为180
    拆分后，形成两个多边形
    再次判断两个多边形是否为均凸多边形，
![uploader](./img/mbi_003.png)
    
      
     
    2.         判断凸多边形是否相交采用 分离轴定理
    两个凸多边形不碰撞，则存在一条直线，两个多边形位于直线两侧
    遍历两个凸多边形的所有边，两个多边形向指定边的投影点集合，集合不相交。
    
    模型检查
    输入：
    项目-建筑-楼层 树结构+模型文件+检查规范
    输出：
    各个检查项的检查结果
    楼层平面图命名规范检查；
    命令名称：SagaCheck
    命令说明：
    1.模型中有且仅有一个-saga后缀的楼层平面视图
    2.带saga标记的楼层平面视图编码符合建模规范要求
    3.是否缺少RF标高，saga平面所在标高应不大于RF标高
    实现逻辑：
    1，  获取需要检查的楼层;floors
    2，  获取所有的平面图名称；floorPlans
    3，  检查是否有且仅有一个-saga后缀的视图;视图符合楼层名称命令规范;（B1,B1M,B1M1,F1,F1M,F2,F2M1,F2M2,F3,RFM,RF）; 检查是否包含RF标高
    4，  记录检查结果
    5，  保存
    单层
    视图名称：F1-saga
    返回值示例：
    图片: https://shimo.im/fake.png
    楼层缺失检查；
    命令名称：FloorMiss
    命令说明：
        检测范围内的楼层文件对应楼层平面图名称应该连续。
    实现逻辑：
    1，  获取需要检查的楼层；floors
    2，  获取楼层的saga标记的平面图名称,
    3，  按名称编码规则从大到小排序；
    4，  检测楼层平面图名称是否重复或连续；
         （B1,B1M,B1M1,F1,F1M,F2,F2M1,F2M2,F3,RFM,RF）
    多层
    视图名称:F1-saga
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             多楼层对比检查
    楼层标高与楼层顺序号检查；
    命令名称：FloorSequenceCheck
    命令说明：
        检查楼层文件当前层标高排序与物理世界楼层顺序号排序是否一致。
    实现逻辑：
    1，  获取需要检查的楼层；floors
        2，获取楼层的saga标记的标高h,
    3，  按标高从大到小排序，依次检查后面的楼层顺序号是否小于前面的，否，则不通过。
     多层
    楼层顺序号
    视图名称：F1-saga
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             多楼层对比检查
    项目长度单位检查；
    命令名称：UnitCheck
    命令说明：
    项目长度单位是否为毫米（mm）
    实现逻辑：
    1，  获取需要检查的楼层；floors
    2，  遍历楼层floors:floor
    3，  获取floor的项目长度单位，判断单位是否为mm,记录
    4，  保存
    单层
    项目单位
    返回值示例：
    图片: https://shimo.im/fake.png
    轴网检查；
    命令名称：GridCheck
    命令说明：
    检查项目下楼层是否共用同一套轴网，同名的轴网需要重合，或延长线重合。
    实现逻辑：
    1，  获取需要检查的楼层；floors
    2，  获取所有楼层floors的所有轴网grids；
    3，  按轴网名称进行分组groups；
    4，  判断每组轴网Curve的Origin, Direction是否相等；Origin可能不相等，投影,判断投影点与Origin是否相等
    多层
    轴网：轴网类型，Start,End,Middle
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             多楼层对比检查
    设备族编码检查；
    命令名称：FamilyNameCheck
    命令说明：
    指定的Revit分类（Category）下的所有对象，族名称应该按照数据字典规定格式进行编码（详见sheet页：参考-revit分类）
    实现逻辑：
    1，  获取需要检查的楼层；floors
    2， 获取需要检查的Reivt分类（Category），例如：机械设备，常规模型；categories
    3， 遍历floors：floor   
        3.1,遍历categories:分类category
        3.2,从模型floor中获取每个分类category下的所有对象；familyInstances
        3.3,按分类族名称进行分组；groups
        3.4,依次检查groups分组内的族名称，是否为可识别类型。
    注：设备四位编码；部件六位编码；信标Beacon 
    参考表：参考-revit分类
    单层
    设备族名称:弯头 - ISBIM
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             结果按族名称进行分组，备注显示此族使用到的楼层。
    部件所在位置检查；
    命令名称：EquipPartLocationCheck
    命令说明：
        部件是否有依赖的设备（数据字典规定，部件必须依赖一个设备）
    实现逻辑：
    12，              获取需要检查的楼层；floors
    13，              遍历floors：floor
    2.1，获取本层所有的部件parts（族编码为六位的）
    2.2，遍历parts：part，检查与part关联的设备是否存在（与part实体相交，设备族的四位编码TDLS与部件六位编码的前四位相等TDLSDW）
    2.3，记录检查结果
             3，保存
    单层
    部件Id：720828
    部件族名称：TDLSDW-低压配电抽屉
    关联设备Id:720899
    返回值示例：
    图片: https://shimo.im/fake.png
    柱边界检查；
    命令名称：ColumnCheck
    命令说明：
             结构柱 是否为空间边界（影响空间范围），建模要求是结构柱，墙为建筑墙
    计算逻辑：
    1， 获取需要检查的楼层；floors
    2， 遍历floors：floor
    2.1，获取本层所有的柱子columns
    2.2，遍历柱子，检查柱子的实例属性“房间边界”是否选中 
    2.3，记录检查结果
             3，保存
![uploader](./img/mbi_004.png)

    单层
    族名称：钢管混凝土柱 - 矩形
    Id:628267
    
    返回值示例：
    图片: https://shimo.im/fake.png
    构件范围检查；
    命令名称：ElementRangeCheck
    命令说明：
    1，正常情况下构件应该位于当前层和上一层之间；
    2，如果上一层为夹层，构件可位于当前层和夹层的上一层之前；
    3，如果当前层是屋顶或屋顶夹层，构件应该位置当前层之上，顶部不约束。
    实现逻辑：
    前置条件：设置冗余范围w=500
    1，获取需要检查的楼层；floors
    2，遍历floors：floor
    2.1，获取本层，saga视图的高度hBase，上一层不为夹层的高度hTop,本层和上一层之间的夹层列表hSandwishes
    2.2，获取本层的柱子（顶部zTop,底部zBase）、空间（顶部zTop,底部zBase）、墙（顶部zTop,底部zBase）、设备（定位点zBase）
    2.3，判断底部zBase,是否位于（hBase-w,hBase）的范围内，顶部hBase是否位于（hTop-w,hTop）的范围内或位置夹层hSandwishes的（t-w,t）之内
    2.4，记录检查结果
    3，保存
    单层
    高度冗余：500mm
    本层标高：3
    顶部标高集合：6，10
    构件Id:628267
    构件族名称：750*500
    构件范围：（0，10）
    
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             需要多层对比检查，需要获取当前层的上一层(依据楼层序列号)
    saga标记位置合法性检查；
    命令名称：SagaPositionCheck
    命令说明：
             推测性检查，指定通过率阈值为80%
        构件范围检测通过率应不低于80%，低于，-saga标记位置可能不正确
    实现逻辑：
    前置条件：进行构件范围检查；获取需要检查的楼层；floors
    1，  遍历floors:floor
    2，  获取本层构件范围检查的通过率，与阈值进行对比
    3，  记录对比结果
    4，  保存
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             这是一个汇总表，业务层实现？？
    连接件检查；
    命令名称：ConnectorCheck
    命令说明：
    1.判断设备是否有连接件（连接件类型：限定水管和风管）;
    2.有连接件的设备是否都已经连接上
    （详见sheet页：参考-连接件对照表）
    实现逻辑：
    1，获取需要检查的楼层；floors
    2，读取“获取预定义的连接件类”表；equipConnectorTbs
    3，遍历floors：floor
    3.1，获取本层的所有构件（设备，部件），存储在familyInstances中; 
    3.2， 遍历familyInstances：fi
    3.2.1，获取构件fi的族编码code; 
    3.2.2，由code从equipConnectorTbs表中取连接件的定义equipConnector
    3.2.3，获取fi的水管连接件和风管连接件，依据equipConnector判断连接件是否存在，连接件是否都连接。
    3.2.4，   记录检查结果。
    4，保存
    参考表：参考-连接件对照表
    单层
    设备Id
    族名称
    
    返回值示例：
    图片: https://shimo.im/fake.png
    系统类型名称检查；
    命令名称：SystemNameCheck
    命令说明：
    模型中系统类型名称与物理世界可识别的拓扑图名称是否一致（详见sheet页：参考-可识别的系统名称）
    实现逻辑：
    1，  获取需要检查的楼层；floors
    2，  读取“获取可识别的管道系统名称”表；systemTypeTbs
    3，  遍历floors：floor
    2.1，获取本层的所有风管系统和水管系统，存储在mepSystemTypes中; 
    2.2， 遍历mepSystemTypes：mepSystemType
    2.2.1，依据mepSystemType的名称，从systemTypeTbs中查找，判断是否存在同名系统， 
    2.2.2，记录判断结果
    4，  保存
    参考表：参考-可识别的系统名称
    单层
    系统名称
    系统类型
    
    
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             需要参考表
    未在空间中的设备；
    命令名称：EquipInSpaceCheck
    命令说明：
        原则上设备和部件都应该在空间中，导出没有空间中的设备，部件
    实现逻辑：
    1，  获取需要检查的楼层；floors
    2，              遍历floors：floor
    2.1，获取本层的所有可识别的构件familyInstances; 
    2.2， 遍历familyInstances：fi
    2.2.1，获取fi所在的空间space，如果 space存在，记录空间id,否则不通过检查
    2.2.2，记录判断结果
    3，              保存
    单层
    族名称：EGCR-门禁-带键盘读卡器
    Id:1530269
    返回值示例：
    图片: https://shimo.im/fake.png
    管网及相关设备检查；
    命令名称：SystemReferEquipCheck
    命令说明：
        检查设备连接的管道系统是否与规范一致。规范（详见sheet页：参考-管网及相关设备）
    实现逻辑：
    1，获取需要检查的楼层；floors
    2， 读取“设备关联的系统类型”表；equipSystemTbs
    3，  遍历floors：floor
    2.1，获取本层的所有可识别的构件familyInstances; 
    2.2， 遍历familyInstances：fi
    2.2.1，获取构件fi的族编码（设备四位或部件六位，TDLS，TDLSDW）；code
    2.2.2，由code,从equipSystemTbs表中取，此code允许连接的系统类型equipSystems；
    2.2.3，取构件fi在模型中连接的系统connectSystems;
    2.2.4，connectSystems与equipSystems求差集和交集，得到未通过检查的系统名称unPressSystems和通过检查的系统名称pressSystems；
    2.2.5，记录判断结果
    4， 保存
    需要参考表：参考-管网及相关设备
    单层
    族名称：EGCR-门禁-带键盘读卡器
    Id:1530269
    通过检查的系统名称：冷却水供水管 4,冷却水回水管 2
    未通过检查的系统名称：冷冻水回水管 2,冷冻水供水管 8
    
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             需要参照表
    Revit族参数完整性检查；
    命令名称：ParameterIntegrityCheck
    命令说明：
             检查设备族参数“设备本地名称”、“设备本地编码”是否缺失
    实现逻辑：
    1，获取需要检查的楼层；floors
    2，遍历floors：floor
    2.1，获取本层的所有可识别的构件familyInstances; 
    2.2，对familyInstances依据族名称进行分组，familyNameGroups
    2.2， 遍历familyNameGroups,取分组集合中的第一构件，判断是否包含“设备本地名称”，“设备本地编码”参数。
    2.3，记录判断结果
    3，保存
    单层
    族名称：EGCR-门禁-带键盘读卡器
    Id:1530269
    返回值示例：
    图片: https://shimo.im/fake.png
    垃圾数据检查
    输入：
    项目-建筑-楼层 树结构+物理世界岗位数据+Revit模型文件
    输出：
    各个检查项的检查结果
    资产与设备信息不一致；
    命令名称：无
    命令说明：
             检查资产与设备同一信息点都有值，值是否相等
    实现逻辑：
    1，  缓存Building下的所有资产；
    2，  缓存Building下的所有岗位；
    遍历所有的岗位，由岗位获取其对应的资产，对比岗位和资产信息点，判断信息点定义相同的信息点，如果有值，值是否相等。
    返回值示例：无
    备注：
             与物理世界交互，与Revit模型无关
    
     输入：项目-建筑-楼层 树结构+物理世界岗位数据+扫楼后台资产数据
     输出：岗位和资产不致的信息点集合
    物理世界中资产岗位关系与二维码中存的关系一致性检查；
    命令名称：无
    命令说明：
        二维码照片存储的资产和岗位是否正确
    实现逻辑：
    1，  获取Buiding下的所有资产；
    2，  缓存二维码照片关系表信息（saas, qrcode/restQRCodeService/queryQRCodeByFmIds）
    关系表中存储的数据：key,fmId,dutyId,projectId
    3，  判断资产是否存在对应岗位，如果存在检查下一条资产，不存在，进行下面判断
    4，  由资产id，查找二维码照片关系表中；是否存在对应资产的关系；如果不存在，检查下一条资产，存在，进行下面判断
    5，  对比资产对应的岗位id和二维码关系中objId，是否相等。
    返回值示例：无
    备注：
             与物理世界交互，与Revit模型无关
     
     输入：项目-建筑-楼层 树结构+扫楼资产数据+saas二维码关系数据
     输出：二维码中岗位与资产中岗位是否一致的检查集合
    
    删除此命令
    物理世界对象与模型一致性检查；
    命令名称：MissDutyOrMode
    命令说明：
    模型√ 对象×  需要重新创建对象
    模型×  对象√ 需要删除对象
    实现逻辑：
    1，  获取Building下所有的楼层；
    2，  遍历楼层；
    3，  缓存本层物理世界的所有对象（设备、部件、信标、空间）数据；A
    4，  由本层模型计算所有可识别对象（设备、部件、信标、空间）数据；B
    5，  3，4数据分别求差集，得到新增和删除对象的数据；
    6，  移除删除的对象中BIMID不完整的数据。（通过台账创建的岗位或模型文件替换）
    7，  导出新增和删除对象的列表。
        注：BIMID完整示例：Fl1223xxx:1233; 
        A与B求差集，得到需要删除的集合
        B与A求差集，得到需要增加的集合
    返回值示例：
    图片: https://shimo.im/fake.png
    备注：
             此处仅返回从模型中取出的数据，后续需要从物理世界取数据，对比得结果。
    
     输入：项目-建筑-楼层 树结构+物理世界岗位数据+Revit模型文件
     输出：需要删除的岗位集合和需要新增的岗位集合
    多个岗位共用一个bimID；
    命令名称：无
    命令说明：
             多个岗位共用一个bimID
    实现逻辑：
    1，  获取当前项目下的所有建筑（Building）A
    2，  遍历A,
    3，  获取Building下所有物理世界的对象；（设备、部件，信标，空间）
    4，  按BIMID进行分组；
    5，  遍历分组，如果分组中对象数量大于1，且对象的BIMID不为空且不为楼层Id，表明此分组对象共用一个BIMID；
        注：对象的BIMID为空或为楼层Id表示些对象为待建模状态。
    返回值示例：无
    备注：
             与物理世界交互，与Revit模型无关
     
     输入：项目-建筑-楼层 树结构+物理世界岗位数据
     输出：岗位共用一个BIMId异常数据集合
    与业务空间有所在关系的设备的实际位置和业务空间位置不一致检查；
    命令名称：无
    命令说明：
    业务空间所在楼层和其中的设备所在楼层一致性检查   
    实现逻辑：
    1，  获取所有楼层；
    2，  获取所有的业务空间类型的集合，得到BusinessSpaceTypes（data-platform-3/infocode/business_space_type/query）
    3，  遍历楼层：
    3.1，查询楼层下的设备，得到设备集合FloorEquips;
    3.2，遍历业务空间类型集合BusinessSpaceTypes; businessSpaceType
    3.3，获取本层businessSpaceType类型的业务空间，得到空间集合businessSpaces；
    3.4，获取与空间关联的设备集合，得到设备集合：businessSpaceEquips
    3.5，设备集合FloorEquips与businessSpaceEquips 求差集，得到设备集合：exceptEquips(即设备所在楼层与业务空间所在楼层不一致的设备); 
        4，输出设备集合：exceptEquips。
     
    返回值示例：无
    备注：
             与物理世界交互，与模型无关
    
     输入：项目-建筑-楼层 树结构+物理世界业务空间类型集合+物理世界业务空间集合+业务空间与设备的图关系+楼层下的设备集合
     输出：业务空间中的设备的楼层与设备自身楼层不一致的集合
    revit模型中的族编码和岗位的设备类编码一致性检查；
    命令名称：无
    命令说明：
    1.       模型中的族编码和岗位的设备类编码是否一致
    实现逻辑：
    1，  获取所有楼层；得到楼层集合:floorList;
    2，  遍历floorList,floor
    2.1，获取物理世界floor下的所有设备和部件集合，得到岗位集合dutyList; 
    2.2，遍历dutyList:duty
          2.2.1，由duty.BIMId，从Revit模型文件中获取模型对象element
          2.2.2，对比岗位中编码与模型文件中获取的编码对比；
          2.2.3，如果编码不一致，保存到错误集合。
     
    返回值示例：
    
     输入：项目-建筑-楼层 树结构+物理世界的岗位数据+Revit模型文件
     输出：岗位编码与模型编码不一致的集合
    
    
