首页 > 其他分享 >osg与IFC(BIM)

osg与IFC(BIM)

时间:2024-08-27 12:15:05浏览次数:5  
标签:BIM void call IFC message include osg

IFC(BIM)

BIM管理中使用的模型格式:IFC

 

IFC简介

IFC模型体系结构由四个层次构成,

从下到上依次是 资源层(Resource Layer)、核心层(Core Layer)、交互层(Interoperability Layer)、领域层(Domain Layer)。

每层中都包含一系列的信息描述模块,并且遵守一个规则:每个层次只能引用同层次和下层的信息资源,而不能引用上层的资源,当上层资源发生变动时,下层是不会受到影响的。

①资源层
IFC体系架构中的最低层,能为其他层所引用。主要是描述标准中用到的基本信息,不针对具体的行业本身,是无整体结构的分散信息,作为描述基础应用于整个信息模型。包括材料资源(Material Resource)、几何限制资源(Geometric Constraint Resource)、成本资源(Costs Resource)等。
②核心层
是IFC体系架构中的第二层,能为交互层与领域层所引用。主要是提供基础的IFC对象模型结构,描述建筑工程信息的整体框架,将资源层信息组织起来,成为一个整体,来反映现实世界的结构。包括核心(The Kernel)和核心扩展(Core Extensions)两个层次的泛化。
③交互层
是IFC体系架构中的第三层,主要是为领域层服务。领域层中的模型可以通过该层来达到信息交互的目的。该层主要解决了领域信息交互的问题,并且在这个层次使各个系统的组成元素细化。包括共享空间元素(SharedSpatialElements)、共享建筑元素(SharedBuildingElements)、共享管理元素(SharedManagement Elements)、共享设备元素(SharedFacilities Elements)和共享建筑服务元素(Shared Bldg Services Elements)等五大类。
④领域层
是IFC体系架构中的最高层。每一个使用或是引用定义在核心和独立资源层上的类信息的模型都是独立的。其主要作用时是深入到各个应用领域的内部,形成专题信息,比如暖通领域(HVAC Domain)、T程管理领域(Construction Management Domain)等,而且还可以根据实际需要不断进行扩展。

==================================================

1) IFC 标准资源层(IFC-Resource Layer):作为整个体系的基本层,IFC 任意层都可引用资源层中的实体。该层主要定义了工程项目的通用信息,这些信息独立于具体建筑,没有整体结构,是分散的基础信息。该层核心内容主要包括属性资源(Property Resource)、表现资源 (Representation Re-source)、结构资源(Structure Resource)。这些实体资源主要用于上层实体资源的定义,以显示上层实体的属性。

2) IFC 标准核心层(IFC-Core Layer):该层之中主要定义了产品、过程、控制等相关信息,主要作用是将下层分散的基础信息组织起来,形成 IFC 模型的基本结构,然后用以描述现实世界中的实物以及抽象的流程。在整个体系之中起到了承上启下的作用。该层提炼定义了适用于整个建筑行业的抽象概念,比如 IFCProduct 实体可以描述建筑项目的建筑场地、建筑空间、建筑构件等。

3) IFC 标准共享层(IFC-Interoperability Layer):共享层主要是服务于领域层,使各个领域间的信息能够交互,同时细化系统的组成元素,具体的建筑构件如板(IFCSlab)、柱(IFCColumn)、梁(IFCBeam)均在这一层被定义。

4) IFC 标准领域层(IFC-Domain Layer):作为 IFC 体系架构的顶层,该层主要定义了面向各个专业领域的实体类型。这些实体都面向各个专业领域具有特定的概念。比如暖通领域(HVAC Domain)的锅炉、管道等。

==================================================

楼层(IfcBuildingStorey):定义水平空间的垂直边界,具有标高属性。楼层与建筑存在关联关系,多个楼层组成了整体的建筑空间,一个楼层可能跨越几个连续的楼层形成复合建筑楼层。

设施(IfcFacility):定义基础设施,例如建筑、道路、桥梁等。

设施组件(IfcFacilityPart):定义基础设施中的组成部分,如桥梁组件(IfcBridgePart)。

场地(IfcSite):定义一个陆地区域,场地可以包括该场地的单个地理参考点的定义(使用经度,纬度和海拔的全球位置)。

空间(IfcSpace):表达具体或抽象的区域边界,是建筑内提供一定功能的区域面积或体积。空间与楼层关联可表示楼层上的房间划分,而与场地关联可表示场地中特定的功能区域。一个空间可能与几个连续的空间形成空间组合,也可以被分解成多个空间。

 

一个基于IFC标准的建筑信息模型有且只能定义一个项目(IfcProject)来作为项目中所有对象的容器,建筑构件大多与楼层或者楼层所拆分的空间建立关联关系,从而确定从属关系以及构件在整个三维模型中的坐标定位。集合关系(IfcRelAggregates)定义一对多的不同空间层次间的从属关系,子空间相互之间通过该关系对象建立从属关系,最终空间结构元素通过该关系对象与项目(IfcProject)建立从属关系。实际的建筑信息模型中可通过集合关系建立一个完整的信息模型空间。

==================================================

IFC格式架构

IFC架构采用EXPRESS语言定义,EXPRESS语言是由STEP开发的概念性架构语言。EXPRESS用于面向对象的信息描述语言,处于STEP的基础和核心地位。它将IFC模型的结构描述为:规范的类,与类相关联的属性,类的约束,以及类与其他约束之间的关系。
IFC架构分为四个层:领域层、共享层、核心层、资源层。

IFC架构将所有的对象与类按概念进行分类:类型、实体、函数、规则、属性集及量集。

IFC数据组成

IFC文件是一种纯文本文件格式,用普通的文本编辑器就可以查看和编辑。
文件以“ISO-10303-21;”开头,以“END-ISO-10303-21;”结束。

中间包括两个部分:一个文件头段和一个数据段
文件头段以“HEADER;”开始,以“ENDSEC;”结束,里面包含了有关ifc文件本身的信息,例如文件描述、使用的ifc标准版本等。

数据段以“DATA;”开始,以“ENDSEC;”结束,里面包含了要交换的工程信息

IFC格式优势

使用IFC格式有以下优势:

  • 实现不同软件之间的信息交换

IFC作为一个标准的公开的数据表达和存储方法,不同软件通过对接IFC标准接口,便可以与其他软件系统交换信息,畅通无阻。

  • 提升建筑项目中的沟通、生产力、时间、成本和质量

通过IFC,可以在建筑项目的整个生命周期中提升沟通、生产力、时间、成本和质量,为全球的建筑专业与设备专业中的流程提升与信息共享建立一个普遍意义的基准。

  • 集中存储多个项目的工程信息

BIM数据库可集中存储多个项目的工程信息,并利用文件管理表、语句管理表和属性管理表对IFC模型进行保存,从而保证IFC建筑信息模型的正确性和完整性。

  • 建筑信息查询效率高

BIM数据库利用文件管理表、语句管理表和属性管理表对IFC模型进行保存,使建筑信息查询效率大大提升。

IFC格式查看与转换

要打开IFC文件,可以使用以下软件:

  • Autodesk Revit

Revit是一种建筑信息建模(BIM)软件,支持IFC格式,并可用于导入、编辑和查看IFC文件。

  • Tekla Structures

这是一种结构工程BIM软件,也可以打开和编辑IFC文件。

  • 在线工具

推荐使用NSDT 3DConvert这个强大的在线3D格式转换工具,可以将IFC、STEP、IGES、3DXML等多种BIM/CAD文件转换为GLTF、STL、OBJ、DAE等格式。

==================================================================

OSG与IFC

读写IFC文件的osg插件(osgdb_ifc)

调用第三方库ifcplusplus 实现osg ifc插件

第三方库:https://github.com/ifcquery/ifcplusplus

转自:https://blog.csdn.net/baidu_41914439/article/details/108078092?spm=1001.2014.3001.5502

 

//ReaderWriterIFC.h
#ifndef READERWRITERIFC_H
#define READERWRITERIFC_H

#include <osgDB/ReaderWriter>

///
// OSG reader plugin for the ".ifc" format.
// 
// This plugin requires the ifcplusplus

class BuildingModel;
class BuildingEntity;
class ReaderSTEP;
class WriterSTEP;
class GeometryConverter;

class ReaderWriterIFC : public osgDB::ReaderWriter
{
    osg::ref_ptr<osg::Group>                    m_rootnode;
    osg::ref_ptr<osg::Switch>                    m_sw_coord_axes;
    osg::ref_ptr<osg::Switch>                    m_sw_model;    
    shared_ptr<GeometryConverter>                m_geometry_converter;
    shared_ptr<ReaderSTEP>                        m_step_reader;
    shared_ptr<WriterSTEP>                        m_step_writer; 
    shared_ptr<BuildingModel>                    m_ifc_model;

public:
    ReaderWriterIFC();

    const char* className() const { return "IFC reader/writer"; }

    virtual ReadResult readObject(const std::string& filename, const Options* options) const
    {
        return readNode(filename, options);
    }

    virtual WriteResult writeObject(const osg::Node& node, const std::string& filename, const Options* options) const
    {
        return writeNode(node, filename, options);
    }

    virtual ReadResult readNode(const std::string& filename, const Options*) const;
    virtual WriteResult writeNode(const osg::Node&, const std::string& filename, const Options*) const;
};

///

#endif
//ReaderWriterIFC.cpp
#include <sstream>
#include <memory>
#ifndef WIN32
#include <strings.h>//for strncasecmp
#endif

//#include <osg/Notify>
//#include <osg/MatrixTransform>
//#include <osg/Material>
#include <osg/StatusCallback>
#include <osg/PositionAttitudeTransform>
//#include <osg/Texture2D>
//#include <osg/Version>
//#include <osgDB/ConvertUTF>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
//#include <osgDB/ReadFile>
//#include <osgDB/Registry>
#include <osgUtil/Optimizer>
//#include <osgAnimation/AnimationManagerBase>
//#include <osgAnimation/Bone>
//#include <osgAnimation/RigGeometry>
//#include <osgAnimation/Skeleton>
//#include <osgAnimation/VertexInfluence>
//#include <osgGA/GUIActionAdapter>

#include <ifcpp/model/BasicTypes.h>
#include <ifcpp/model/BuildingModel.h>
#include <ifcpp/model/BuildingException.h>
#include <ifcpp/model/BuildingGuid.h>
#include <ifcpp/reader/ReaderSTEP.h>
#include <ifcpp/reader/ReaderUtil.h>
#include <ifcpp/writer/WriterSTEP.h>
#include <ifcpp/IFC4/include/IfcProduct.h>
#include <ifcpp/IFC4/include/IfcSite.h>
#include <ifcpp/IFC4/include/IfcLengthMeasure.h>
#include <ifcpp/IFC4/include/IfcOpeningElement.h>
#include <ifcpp/IFC4/include/IfcOwnerHistory.h>
#include <ifcpp/IFC4/include/IfcGloballyUniqueId.h>
#include <ifcpp/geometry/Carve/GeometryConverter.h>
#include <ifcpp/geometry/Carve/ConverterOSG.h>

#if defined(_MSC_VER)
    #pragma warning( disable : 4505 )
    #pragma warning( default : 4996 )
#endif

#include "ReaderWriterIFC.h"

/// Returns true if the given node is a basic root group with no special information.
/// Used in conjunction with UseFbxRoot option.
/// Identity transforms are considered as basic root nodes.
bool isBasicRootNode(const osg::Node& node)
{
    const osg::Group* osgGroup = node.asGroup();
    if (!osgGroup || node.asGeode())        // WriterNodeVisitor handles Geodes the "old way" (= Derived from Node, not Group as for now). Geodes may be considered "basic root nodes" when WriterNodeVisitor will be adapted.
    {
        // Geodes & such are not basic root nodes
        return false;
    }

    // Test if we've got an empty transform (= a group!)
    const osg::Transform* transform = osgGroup->asTransform(); 
    if (transform)
    {
        const osg::PositionAttitudeTransform* pat = transform->asPositionAttitudeTransform();
        if (const osg::MatrixTransform* matrixTransform = transform->asMatrixTransform())
        {
            if (!matrixTransform->getMatrix().isIdentity())
            {
                // Non-identity matrix transform
                return false;
            }
        }
        else if ( pat )
        {
            if (pat->getPosition() != osg::Vec3d() ||
                pat->getAttitude() != osg::Quat() ||
                pat->getScale() != osg::Vec3d(1.0f, 1.0f, 1.0f) ||
                pat->getPivotPoint() != osg::Vec3d())
            {
                // Non-identity position attribute transform
                return false;
            }
        }
        else
        {
            // Other transform (not identity or not predefined type)
            return false;
        }
    }

    // Test the presence of a non-empty stateset
    if (node.getStateSet())
    {
        osg::ref_ptr<osg::StateSet> emptyStateSet = new osg::StateSet;
        if (node.getStateSet()->compare(*emptyStateSet, true) != 0)
        {
            return false;
        }
    }

    return true;
}


ReaderWriterIFC::ReaderWriterIFC()
{
    supportsExtension("ifc", "IFC format");
    supportsOption("Embedded", "(Write option) Embed textures in IFC file");
    supportsOption("UseFbxRoot", "(Read/write option) If the source OSG root node is a simple group with no stateset, the writer will put its children directly under the IFC root, and vice-versa for reading");
    supportsOption("LightmapTextures", "(Read option) Interpret texture maps as overriding the lighting. 3D Studio Max may export files that should be interpreted in this way.");
    supportsOption("TessellatePolygons", "(Read option) Tessellate mesh polygons. If the model contains concave polygons this may be necessary, however tessellating can be very slow and may erroneously produce triangle shards.");
    m_ifc_model = shared_ptr<BuildingModel>(new BuildingModel());
    m_geometry_converter = shared_ptr<GeometryConverter>(new GeometryConverter(m_ifc_model));
    m_step_reader = shared_ptr<ReaderSTEP>(new ReaderSTEP());
    m_step_writer = shared_ptr<WriterSTEP>(new WriterSTEP());
    m_rootnode = new osg::Group();
    m_rootnode->setName("m_rootnode");

    m_sw_model = new osg::Switch();
    m_sw_model->setName("m_sw_model");
    m_rootnode->addChild(m_sw_model.get());

    m_sw_coord_axes = new osg::Switch();
    m_sw_coord_axes->setName("m_sw_coord_axes");
    m_rootnode->addChild(m_sw_coord_axes.get());
}
std::wstring StringToWstring(const std::string str)
{// string转wstring
    unsigned len = str.size() * 2;// 预留字节数
    setlocale(LC_CTYPE, "");     //必须调用此函数
    wchar_t *p = new wchar_t[len];// 申请一段内存存放转换后的字符串
    mbstowcs(p, str.c_str(), len);// 转换
    std::wstring str1(p);
    delete[] p;// 释放申请的内存
    return str1;
}
osgDB::ReaderWriter::ReadResult
ReaderWriterIFC::readNode(const std::string& filenameInit,
                          const Options* options) const
{
    try
    {
        std::string ext(osgDB::getLowerCaseFileExtension(filenameInit));
        if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
        std::string filename(osgDB::findDataFile(filenameInit, options));
        if (filename.empty()) return ReadResult::FILE_NOT_FOUND;
        // first remove previously loaded geometry from scenegraph
        osg::ref_ptr<osg::Switch> model_switch = m_sw_model;        SceneGraphUtils::clearAllChildNodes(model_switch);
        // reset the IFC model
        shared_ptr<GeometryConverter> geometry_converter = m_geometry_converter;
        geometry_converter->clearMessagesCallback();
        geometry_converter->resetModel();
        std::stringstream err;

        try
        {
            osg::StatusCallback& statusCallBack = osg::StatusCallback::getStatusCallback();
            void* obj = statusCallBack.getMessageCallBack_obj();
            osg::StatusCallback::Func_call_on_message func = statusCallBack.getMessageCallBack_func();
            geometry_converter->setMessageCallBack_extern(obj,func);
            m_step_reader->setMessageCallBack_extern(obj, func);
            // load file to IFC model
            std::wstring fileName = StringToWstring(filenameInit);
            m_step_reader->loadModelFromFile(fileName, geometry_converter->getBuildingModel());

            // convert IFC geometric representations into Carve geometry
            const double length_in_meter = geometry_converter->getBuildingModel()->getUnitConverter()->getLengthInMeterFactor();
            geometry_converter->setCsgEps(1.5e-08*length_in_meter);
            geometry_converter->convertGeometry();
            // convert Carve geometry to OSG
            shared_ptr<ConverterOSG> converter_osg(new ConverterOSG(geometry_converter->getGeomSettings()));
            converter_osg->setMessageCallBack_extern(obj, func);
            converter_osg->convertToOSG(geometry_converter->getShapeInputData(), model_switch);

            // in case there are IFC entities that are not in the spatial structure
            const std::map<std::string, shared_ptr<BuildingObject> >& objects_outside_spatial_structure = geometry_converter->getObjectsOutsideSpatialStructure();
            if (objects_outside_spatial_structure.size() > 0)
            {
                osg::ref_ptr<osg::Switch> sw_objects_outside_spatial_structure = new osg::Switch();
                sw_objects_outside_spatial_structure->setName("IfcProduct objects outside spatial structure");
                converter_osg->addNodes(objects_outside_spatial_structure, sw_objects_outside_spatial_structure);
                if (sw_objects_outside_spatial_structure->getNumChildren() > 0)
                {
                    model_switch->addChild(sw_objects_outside_spatial_structure);
                }
            }
        }
        catch (OutOfMemoryException& e)
        {
            throw e;
        }
        catch (BuildingException& e)
        {
            err << e.what();
        }
        catch (std::exception& e)
        {
            err << e.what();
        }
        catch (...)
        {
            err << "loadModelFromFile, createGeometryOSG failed" << std::endl;
        }
        try
        {
            if (model_switch)
            {
                bool optimize = true;
                if (optimize)
                {
                    osgUtil::Optimizer opt;
                    opt.optimize(model_switch);
                }

                // if model bounding sphere is far from origin, move to origin
                const osg::BoundingSphere& bsphere = model_switch->getBound();
                if (bsphere.center().length() > 10000)
                {
                    if (bsphere.center().length() / bsphere.radius() > 100)
                    {
                        std::unordered_set<osg::Geode*> set_applied;
                        SceneGraphUtils::translateGroup(model_switch, -bsphere.center(), set_applied);
                    }
                }
            }
        }
        catch (std::exception& e)
        {
            err << e.what();
        }
        geometry_converter->clearInputCache();
        if (err.tellp() > 0)
        {
            throw BuildingException(err.str().c_str());
        }
        bool refCoordSysChange = false;
        osg::Matrix mat;
        //if (zUp)
        {
            //if (eUp != FbxAxisSystem::eZAxis || fSign != 1.0 || upSign != 1.0)
            {
 /*               switch (eUp)
                {
                case FbxAxisSystem::eXAxis:
                    mat.set(0, fSign, 0, 0, -fSign, 0, 0, 0, 0, 0, HorizSign, 0, 0, 0, 0, 1);
                    break;
                case FbxAxisSystem::eYAxis:
                    mat.set(1, 0, 0, 0, 0, 0, -fSign * HorizSign, 0, 0, fSign, 0, 0, 0, 0, 0, 1);
                    break;
                case FbxAxisSystem::eZAxis:
                    mat.set(1, 0, 0, 0, 0, fSign, 0, 0, 0, 0, fSign * HorizSign, 0, 0, 0, 0, 1);
                    break;
                }*/
                refCoordSysChange = true;
            }
        }
        //else //if (fbxAxis != FbxAxisSystem::OpenGL)
        {
            //switch (eUp)
            //{
            //case FbxAxisSystem::eXAxis:
            //    mat.set(0, -fSign, 0, 0, fSign, 0, 0, 0, 0, 0, HorizSign, 0, 0, 0, 0, 1);
            //    break;
            //case FbxAxisSystem::eYAxis:
            //    mat.set(1, 0, 0, 0, 0, -fSign, 0, 0, 0, 0, -fSign * HorizSign, 0, 0, 0, 0, 1);
            //    break;
            //case FbxAxisSystem::eZAxis:
            //    mat.set(1, 0, 0, 0, 0, 0, fSign * HorizSign, 0, 0, -fSign, 0, 0, 0, 0, 0, 1);
            //    break;
            //}
           // refCoordSysChange = true;
        }
        if (refCoordSysChange)
        {
            osg::Transform* pTransformTemp = model_switch->asTransform();
            osg::MatrixTransform* pMatrixTransform = pTransformTemp ?
                pTransformTemp->asMatrixTransform() : NULL;
            if (pMatrixTransform)
            {
                pMatrixTransform->setMatrix(pMatrixTransform->getMatrix() * mat);
            }
            else
            {
                pMatrixTransform = new osg::MatrixTransform(mat);
                if (isBasicRootNode(*model_switch))
                {  
                    osg::Group* osgGroup = model_switch->asGroup();
                    for(unsigned int i = 0; i < osgGroup->getNumChildren(); ++i)
                    {
                        pMatrixTransform->addChild(osgGroup->getChild(i));
                    }
                    pMatrixTransform->setName(osgGroup->getName());
                }
                else
                {
                    pMatrixTransform->addChild(model_switch);
                }
            }
            //model_switch = pMatrixTransform;
        }
        model_switch->setName(filenameInit);
        return model_switch;        
    }
    catch (...)
    {
        OSG_WARN << "Exception thrown while importing \"" << filenameInit << '\"' << std::endl;
    }

    return ReadResult::ERROR_IN_READING_FILE;
}

osgDB::ReaderWriter::WriteResult ReaderWriterIFC::writeNode(
    const osg::Node& node,
    const std::string& filename,
    const Options* options) const
{
    try
    {
        shared_ptr<GeometryConverter> geom_converter = m_geometry_converter;
        shared_ptr<BuildingModel>& model = geom_converter->getBuildingModel();
        std::wstring m_file_path = StringToWstring(filename);
        model->initFileHeader(m_file_path);
        std::stringstream stream;
        m_step_writer->writeModelToStream(stream, model);
        FILE * pFile = fopen(filename.c_str(), "wt");
        if (pFile==nullptr)
        {
            return false;
        }
        fprintf(pFile, "%s", stream.str().c_str());
        fclose(pFile);
        return WriteResult::FILE_SAVED;
    }
    catch (const std::string& s)
    {
        return s;
    }
    catch (const char* s)
    {
        return std::string(s);
    }
    catch (...)
    {
    }
    return WriteResult::ERROR_IN_WRITING_FILE;
}

///
// Add ourself to the Registry to instantiate the reader/writer.

REGISTER_OSGPLUGIN(ifc, ReaderWriterIFC)

对osg库中增加了StatusCallback来和ifcplusplus库中的对应

//StatusCallback
//消息回调
#pragma once

#include <osg/Export>
#include <sstream>
#include <iostream>
#include <vector>

//#include "OpenMPIncludes.h"
namespace osg 
{
    using namespace std;
    class OSG_EXPORT StatusCallback
    {
    public:
        typedef void(*Func_call_on_message)(void*, std::string type, std::wstring msg,double v);
        typedef bool(*Func_call_CancelCheck)(void*);
        static StatusCallback& getStatusCallback();
        StatusCallback() = default;
        virtual ~StatusCallback() = default;

        void setMessageCallBack(void* obj_ptr, Func_call_on_message func)
        {
            m_obj_call_on_message = obj_ptr;
            m_func_call_on_message = func;
        }
        void* getMessageCallBack_obj(){return m_obj_call_on_message;}
        Func_call_on_message getMessageCallBack_func(){return m_func_call_on_message;}        
        virtual void setMessageTarget(StatusCallback* other)
        {
            m_redirect_target = other;
        }

        virtual void unsetMessageCallBack()
        {
            m_obj_call_on_message = nullptr;
            m_func_call_on_message = nullptr;
        }
        virtual void setCancelCheck(void* obj_ptr, Func_call_CancelCheck func)
        {
            m_obj_call_check_cancel = obj_ptr;
            m_func_check_cancel = func;
        }

        virtual void unsetCancelCheck()
        {
            m_obj_call_check_cancel = nullptr;
            m_func_check_cancel = nullptr;
        }
        //\brief trigger the callback to pass a message, warning, or error, for example to store in a logfile
        virtual void messageCallback( std::string type,std::wstring msg, double v)
        {
            if (m_redirect_target)
            {
                m_redirect_target->messageCallback(type, msg, v);
                return;
            }
            if (m_func_call_on_message)
            {
                if (m_obj_call_on_message)
                {
    #ifdef ENABLE_OPENMP
                    // Note: this lock protects accesses only for this instance. If several StatusCallback (or derived) objects are bound to the same callback function, a lock is necessary there.
                    ScopedLock lock(m_writelock);
    #endif
                    m_func_call_on_message(m_obj_call_on_message,type, msg, v);
                }
            }
        }
        //\brief check if cancellation has been requested.
        virtual bool isCanceled()
        {
            if (m_redirect_target)
            {
                return m_redirect_target->isCanceled();
            }
            if (m_func_check_cancel)
            {
                if (m_obj_call_check_cancel)
                {
    #ifdef ENABLE_OPENMP
                    // Note: this lock protects accesses only for this instance. If several StatusCallback (or derived) objects are bound to the same callback function, a lock is necessary there.
                    ScopedLock lock(m_writelock);
    #endif
                    return m_func_check_cancel(m_obj_call_check_cancel);
                }
            }
            return false;
        }
    protected:
        //\brief Pointer to the object on which the message callback function is called.
        void* m_obj_call_on_message = nullptr;
        //\brief Pointer to the object on which the cancel check function is called.
        void* m_obj_call_check_cancel = nullptr;
        //附加的消息回调,在有消息时进行响应,以支持库外使用
        Func_call_on_message m_func_call_on_message = nullptr;
        //\brief Pointer to the predicate that determines whether an operation should be canceled.
        Func_call_CancelCheck m_func_check_cancel = nullptr;
        StatusCallback* m_redirect_target = nullptr;
    #ifdef ENABLE_OPENMP
        Mutex m_writelock;
    #endif
    };
}

 

//StatusCallback.cpp
#include <osg/StatusCallback>
using namespace osg;
StatusCallback _StatusCallback;
StatusCallback& StatusCallback::getStatusCallback() { return _StatusCallback; }

在使用时添加作为回调

void messageTarget(void* ptr,std::string type, std::wstring msg,double v)
{
    MainWindow* myself = (MainWindow*)ptr;
    if (myself)
    {
#ifdef ENABLE_OPENMP
        ScopedLock lock(myself->m_mutex_messages);
#endif
        if(v<0)
            emit myself->TxtOut(QString::fromStdString(type),QString::fromStdWString(msg));
        else
        {
            emit myself->ProgressValue(v,QString::fromStdString(type));
        }
    }
}

在初始化时调用

    osg::StatusCallback& gloableStatus = osg::StatusCallback::getStatusCallback();
    gloableStatus.setMessageCallBack(this, messageTarget);

ifcplusplus库中也要做相应修改

/* -*-c++-*- IfcQuery www.ifcquery.com
*
MIT License

Copyright (c) 2017 Fabian Gerold

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.
*/

#pragma once

#include <sstream>
#include <iostream>
#include <vector>
#include "BasicTypes.h"
#include "GlobalDefines.h"
#include "OpenMPIncludes.h"

class BuildingEntity;

class IFCQUERY_EXPORT StatusCallback
{
public:
    typedef void(*Func_call_on_message)(void*, std::string type, std::wstring msg, double v);
    enum MessageType
    {
        MESSAGE_TYPE_UNKNOWN,
        MESSAGE_TYPE_GENERAL_MESSAGE,
        MESSAGE_TYPE_PROGRESS_VALUE,    //\brief Progress mechanism to update progress bar or similar.
        MESSAGE_TYPE_PROGRESS_TEXT,        //\brief Progress mechanism to update text in progress bar or similar.
        MESSAGE_TYPE_MINOR_WARNING,
        MESSAGE_TYPE_WARNING,
        MESSAGE_TYPE_ERROR,
        MESSAGE_TYPE_CLEAR_MESSAGES,
        MESSAGE_TYPE_CANCELED
    };
    /*\class Message
      \brief Combines all information about a status message, being it a general message, a warning, error, or a notification about a progress (for example during reading of a file).
    */
    class Message
    {
    public:
        //\brief Default constructor.
        Message()
        {
            m_message_type = MessageType::MESSAGE_TYPE_UNKNOWN;
            m_reporting_function = "";
            m_entity = nullptr;
            m_progress_value = -1;
        }

        std::wstring m_message_text;        // Message text.
        MessageType m_message_type;            // Type of message (warning, error etc.).
        const char* m_reporting_function;    // Function name where the message is sent from. You can use the __FUNC__ macro from BuildingException.h.
        BuildingEntity* m_entity;            // IFC entity in case the message applies to a certain entity.

        double m_progress_value;            // Value of progress [0...1]. If negative value is given, the progress itself is ignored, for example when only the progress text is updated.
        std::string m_progress_type;        // Type of progress, for example "parse", "geometry".
        std::wstring m_progress_text;        // A text that describes the current actions. It can be used for example to set a text on the progress bar.
    };

    StatusCallback() = default;
    virtual ~StatusCallback() = default;

    //\brief error callback mechanism to show messages in gui
    virtual void setMessageCallBack(void* obj_ptr, void(*func)(void*, shared_ptr<Message> t))
    {
        m_obj_call_on_message = obj_ptr;
        m_func_call_on_message = func;
    }    
    void setMessageCallBack_extern(void* obj_ptr, Func_call_on_message func)
    {
        m_obj_call_on_msg_extern = obj_ptr;
        m_func_call_on_msg_extern = func;
    }

    virtual void unsetMessageCallBack_extern()
    {
        m_obj_call_on_msg_extern = nullptr;
        m_func_call_on_msg_extern = nullptr;
    }
    virtual void setMessageTarget(StatusCallback* other)
    {
        m_redirect_target = other;
    }

    virtual void unsetMessageCallBack()
    {
        m_obj_call_on_message = nullptr;
        m_func_call_on_message = nullptr;
    }

    virtual void setCancelCheck(void* obj_ptr, bool(*func)(void*))
    {
        m_obj_call_check_cancel = obj_ptr;
        m_func_check_cancel = func;
    }

    virtual void unsetCancelCheck()
    {
        m_obj_call_check_cancel = nullptr;
        m_func_check_cancel = nullptr;
    }

    //\brief trigger the callback to pass a message, warning, or error, for example to store in a logfile
    virtual void messageCallback(shared_ptr<Message> m)
    {
        if (m_redirect_target)
        {
            m_redirect_target->messageCallback(m);
            return;
        }

#ifdef _DEBUG
        if (!m_func_call_on_message || !m_obj_call_on_message)
        {
            if (m)
            {
                switch (m->m_message_type)
                {
                case MESSAGE_TYPE_UNKNOWN:
                case MESSAGE_TYPE_GENERAL_MESSAGE:
                case MESSAGE_TYPE_MINOR_WARNING:
                case MESSAGE_TYPE_WARNING:
                case MESSAGE_TYPE_ERROR:
                    std::wcout << L"messageCallback not set. Lost message: " << m->m_message_text.c_str() << std::endl;
                    break;
                }
            }
        }

        if (m->m_message_type == MESSAGE_TYPE_ERROR)
        {
            std::wcout << L"error: " << m->m_message_text.c_str() << std::endl;
        }
#endif

        if (m_func_call_on_message)
        {
            if (m_obj_call_on_message)
            {
#ifdef ENABLE_OPENMP
                // Note: this lock protects accesses only for this instance. If several StatusCallback (or derived) objects are bound to the same callback function, a lock is necessary there.
                ScopedLock lock(m_writelock);
#endif
                m_func_call_on_message(m_obj_call_on_message, m);
            }
        }
        if (m_func_call_on_msg_extern)
        {
            if (m_obj_call_on_msg_extern)
            {
#ifdef ENABLE_OPENMP
                // Note: this lock protects accesses only for this instance. If several StatusCallback (or derived) objects are bound to the same callback function, a lock is necessary there.
                ScopedLock lock(m_writelock);
#endif
                std::string msgType;
                switch (m->m_message_type)
                {
                case MESSAGE_TYPE_UNKNOWN:
                    msgType = "UNKNOWN";
                    break;
                case MESSAGE_TYPE_GENERAL_MESSAGE:
                    msgType = "GENERAL_MESSAGE";
                    break;
                case MESSAGE_TYPE_PROGRESS_VALUE:
                    msgType = "PROGRESS_VALUE";
                    break;
                case MESSAGE_TYPE_PROGRESS_TEXT:
                    msgType = "PROGRESS_TEXT";
                    break;
                case MESSAGE_TYPE_MINOR_WARNING:
                    msgType = "MINOR_WARNING";
                    break;
                case MESSAGE_TYPE_WARNING:
                    msgType = "WARNING";
                    break;
                case MESSAGE_TYPE_ERROR:
                    msgType = "ERROR";
                    break;
                }
                if(m->m_progress_value>=0)
                    m_func_call_on_msg_extern(m_obj_call_on_msg_extern, m->m_progress_type, m->m_progress_text,m->m_progress_value);
                else
                    m_func_call_on_msg_extern(m_obj_call_on_msg_extern, msgType, m->m_message_text, m->m_progress_value);
            }
        }
    }

    //\brief check if cancellation has been requested.
    virtual bool isCanceled()
    {
        if (m_redirect_target)
        {
            return m_redirect_target->isCanceled();
        }

        if (m_func_check_cancel)
        {
            if (m_obj_call_check_cancel)
            {
#ifdef ENABLE_OPENMP
                // Note: this lock protects accesses only for this instance. If several StatusCallback (or derived) objects are bound to the same callback function, a lock is necessary there.
                ScopedLock lock(m_writelock);
#endif
                return m_func_check_cancel(m_obj_call_check_cancel);
            }
        }

        return false;
    }

    virtual void messageCallback(const std::string& message_text, MessageType type, const char* reporting_function, BuildingEntity* entity = nullptr)
    {
        shared_ptr<Message> message(new Message());
        message->m_message_text.assign(message_text.begin(), message_text.end());
        message->m_message_type = type;
        message->m_reporting_function = reporting_function;
        message->m_entity = entity;
        messageCallback(message);
    }
    virtual void messageCallback(const std::wstring& message_text, MessageType type, const char* reporting_function, BuildingEntity* entity = nullptr)
    {
        shared_ptr<Message> message(new Message());
        message->m_message_text.assign(message_text);
        message->m_message_type = type;
        message->m_reporting_function = reporting_function;
        message->m_entity = entity;
        messageCallback(message);
    }
    virtual void progressValueCallback(double progress_value, const std::string& progress_type)
    {
        shared_ptr<Message> progress_message(new Message());
        progress_message->m_message_type = MessageType::MESSAGE_TYPE_PROGRESS_VALUE;
        progress_message->m_progress_value = progress_value;
        progress_message->m_progress_type.assign(progress_type);
        messageCallback(progress_message);
    }
    virtual void progressTextCallback(const std::wstring& progress_text)
    {
        shared_ptr<Message> progress_message(new Message());
        progress_message->m_message_type = MessageType::MESSAGE_TYPE_PROGRESS_TEXT;
        progress_message->m_progress_value = 0;
        progress_message->m_progress_text.assign(progress_text);
        messageCallback(progress_message);
    }
    virtual void clearMessagesCallback()
    {
        shared_ptr<Message> progress_message(new Message());
        progress_message->m_message_type = MessageType::MESSAGE_TYPE_CLEAR_MESSAGES;
        messageCallback(progress_message);
    }
    virtual void canceledCallback()
    {
        shared_ptr<Message> canceled_message(new Message());
        canceled_message->m_message_type = MessageType::MESSAGE_TYPE_CANCELED;
        messageCallback(canceled_message);
    }

protected:
    //\brief Pointer to the object on which the message callback function is called.
    void* m_obj_call_on_message = nullptr;
    void* m_obj_call_on_msg_extern = nullptr;

    //\brief Pointer to the object on which the cancel check function is called.
    void* m_obj_call_check_cancel = nullptr;

    //\brief Pointer to the callback function for messages.
    void(*m_func_call_on_message)(void*, shared_ptr<Message> t) = nullptr;
    //附加的消息回调,在有消息时进行响应,以支持库外使用
    Func_call_on_message m_func_call_on_msg_extern = nullptr;

    //\brief Pointer to the predicate that determines whether an operation should be canceled.
    bool(*m_func_check_cancel)(void*) = nullptr;

    StatusCallback* m_redirect_target = nullptr;

#ifdef ENABLE_OPENMP
    Mutex m_writelock;
#endif
};

 

==========================================================

 

 

标签:BIM,void,call,IFC,message,include,osg
From: https://www.cnblogs.com/lyggqm/p/18382418

相关文章

  • 3D轻量化新利器!Archicad采用HOOPS技术,提升BIM应用竞赛力
    行业:建筑行业挑战:如何实际发现不同软件之间的数据格式的协同与转换?如何提供高级软件的性能和轻量化渲染效果?如何增加新的功能和扩展性?解决方案:HOOPSExchange为其解决3D模型格式转换问题,HOOPSVisualize与HOOPSCommunicator的应用,为其解决可视化和Web端3D模型轻量化问题。......
  • osg,objectarx及occt之间矩阵的转换
    osg的矩阵表达形式为osg::MatrixObjectArx的矩阵表达式为AcGeMatrix3docct的矩阵表达式分gp_Trsf及支持变形的gp_GTrsf osg矩阵转化为ObjectArxosg::MatrixmVPW;TcGeMatrix3dmatrix;for(inti=0;i<4;++i){for(intj=0;j<4;++j){matr......
  • OSGI
    OSGI基础概述概述:OSGI是OpenServicesGatewayinitiative的缩写,叫做开放服务网关协议,通常可能指OSGi联盟、OSGi标准或者OSGi框架。OSGI:OSGI联盟现在将OSGI定义为一种技术,该技术是指一系列用于定义Java动态化组件系统的标准。这些标准通过为大型分布式系统以及嵌入式系统提供一......
  • 【Linux或者Windows中相关网络工具使用介绍】nc、ping、ifconfig、ipaddr、tcpdump、l
    在实际的网络排错、运维诊断、或者是开发过程中,熟练运用Linux或者Windows当中的有关网络工具,能够助力我们更迅速更精准地定位故障。因而,今天给大家分享几款必掌握的网络利器。1.nc命令在Linux中,nc命令即netcat命令,它被称为网络工具中的“瑞士军刀”,是一个功能强大的......
  • Apache COC闪电演讲总结【OSGraph】
     大家能看到我最近一直在折腾与OSGraph这个产品相关的事情,之前在文章《妙用OSGraph:发掘GitHub知识图谱上的开源故事》中向大家阐述过这个产品的设计理念和应用价值。比方说以下问题就可以在OSGraph上找到明确的答案。 从技术角度说,我们是用GitHub开放数据结合图技术(TuGrap......
  • DMA_IFCR清除DMA_ISR标志位,写1清除,还是写0清除?
    先说结论:DMA_IFCR的各位通过写"1"来清除DMA_ISR中的各中断状态标志位!        最近在学习DMA,看的原子教你玩转STM32库函数版的书,里面就DMA_IFCR清除DMA_ISR标志位的问题,原文写的是《DMA_IFCR的各位就是用来清除DMA_ISR的对应位的,通过写0清除。在DMA_ISR被置位......
  • 一种倾斜摄影网格简化方式:指定LOD层级裁剪输出为FBX/OBJ/OSGB/3DTiles
    工具OSGB源数据灵易智模·倾斜摄影编辑平台(下称OPEditor)引言指定LOD层级与网格简化的关系倾斜摄影模型本身就是通过逐级简化点云得到的分页金字塔数据,因此它每一级都是下一级的网格简化结果,且算法成熟、结果可控;通过在导出即输出数据时,设置源数据的最大参考层级来直接......
  • win系统 python 安装 osgeo库安装(最简单)
    Python osgeo库安装用法介绍安装使用osgeo库,本质是安装gdal一、下载对应python版本压缩包下载地址在结尾二、解压压缩包在解压之后的文件夹当中,找到这两个文件夹三、复制文件夹到python安装目录当中如python环境文件夹路径为D:\Local\Programs\miniconda3\envs\py31......
  • iOS开发基础125-深入探索SDWebImage
    SDWebImage是一个流行的用于处理图像下载和缓存的库,广泛用于iOS开发中,提供了一系列方便的API来下载和缓存图像,以提高应用的性能和用户体验。以下是对其进行详细介绍和分析,包括其原理和底层实现。一、SDWebImage的主要功能图像下载和缓存:图像下载:使用异步方式从网络上下......
  • 5 SAP前台操作手册-PP模块-计划独立需求(PIR)创建、修改(删除)、显示(MD061,MD62,MD63
    0总体说明SAP实施项目中,到了第3个阶段-系统实现,在这个阶段,因为蓝图汇报已经结束,配置也差不多完成了,自开发还在进行中,SAP标准功能下,可以进行基础业务的前台操作了,在实现阶段的末端,客户指定的关键用户(俗称KU-KeyUser)会进行前台业务操作和练习,提高熟练程度,同时需要在外部SAP顾......