/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// // ODA Platform #include "OdaCommon.h" #include "RxDynamicModule.h" #include "RxVariantValue.h" #include "DynamicLinker.h" // Visualize SDK #include "TvFactory.h" #include "TvGeomCollector.h" #include "TvFilerTimer.h" #include "TvDatabaseUtils.h" //XML import #include "Xml2Visualize.h" #include "TvFilerTimer.h" #include "TvDatabaseUtils.h" #include using namespace XML2Visualize; ODRX_DEFINE_DYNAMIC_MODULE(OdTvXml2VisualizeFilerModule); int streamBufCallBack(void* streamBuf, char* buffer, int n) { OdStreamBuf* buf = static_cast(streamBuf); OdUInt64 _n = n; OdUInt64 curPos = buf->tell(); OdUInt64 totalLen = buf->length(); OdUInt64 bytesToRead = std::min(_n, totalLen - curPos); buf->getBytes(buffer, bytesToRead); return bytesToRead; } static void applyMaterial(OdTvDatabasePtr& pDb, OdTvEntityPtr& entPtr) { OdString strMaterialName = OD_T("XML_DEFAULT_MATERIAL"); OdTvResult retCode; OdTvMaterialId materialId = pDb->createMaterial(strMaterialName, &retCode); if (retCode == tvOk) { OdTvMaterialPtr pDefaultMaterial = materialId.openObject(OdTv::kForWrite); if (!pDefaultMaterial.isNull()) { OdTvMaterialColor matColor; matColor.setColor(OdTvColorDef(255, 255, 255)); pDefaultMaterial->setSpecular(matColor, 0.3); entPtr->setMaterial(materialId); } } } OdTvVisualizeXmlFiler::OdTvVisualizeXmlFiler() : m_properties(OdTvVisualizeXmlFilerProperties::createObject()) { } OdTvVisualizeFilerPtr OdTvXml2VisualizeFilerModule::getVisualizeFiler() const { OdTvVisualizeFilerPtr pStlFiler = new OdTvVisualizeXmlFiler(); return pStlFiler; } OdTvDatabaseId OdTvVisualizeXmlFiler::loadFrom(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvDatabaseId tvDbId; OdTvModelId modelId; LoadXmlOptions opt(filePath); importXml(tvDbId, modelId, opt, pProfileRes, rc); return tvDbId; } OdTvDatabaseId OdTvVisualizeXmlFiler::loadFrom(OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvDatabaseId tvDbId; OdTvModelId modelId; LoadXmlOptions opt(pBuffer); importXml(tvDbId, modelId, opt, pProfileRes, rc); return tvDbId; } OdTvDatabaseId OdTvVisualizeXmlFiler::loadFrom(OdDbBaseDatabase* pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { if (rc) *rc = tvNotImplementedYet; return OdTvDatabaseId(); } bool OdTvVisualizeXmlFiler::importXml(OdTvDatabaseId& databaseId, OdTvModelId& tvModelId, const LoadXmlOptions& opt, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { bool bUseTimeProfiling = false; if (pProfileRes) bUseTimeProfiling = true; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); OdString filename; OdLandLandXMLPtr db; xmlDocPtr doc = NULL; if (rc) *rc = tvOk; if (opt.m_type == LoadXmlOptions::kFilePath) { filename = OdTvDatabaseUtils::getFileNameFromPath(opt.m_filePath); doc = xmlParseFile(opt.m_filePath); } else if (opt.m_type == LoadXmlOptions::kBuffer) { // for test loading from buffer // OdStreamBufPtr buf = odrxSystemServices()->createFile(opt.m_filePath, Oda::FileAccessMode(Oda::kFileRead), Oda::kShareDenyWrite, Oda::kOpenExisting); filename = opt.m_pBuffer->fileName(); doc = xmlReadIO(streamBufCallBack, NULL, opt.m_pBuffer, NULL, NULL, 0); } if (doc == 0) { if (rc) *rc = tvInvalidInput; return false; } db = OdLandLandXML::createObject(); db->readXml((xmlNode*)xmlDocGetRootElement(doc)); if (!db->isLandXml()) { if (rc) *rc = tvInvalidInput; return false; } timing.startVectorizing(); db->compose(); timing.endVectorizing(); timing.endTotal(); //prepare timing object OdTvFilerTimer tvTiming(bUseTimeProfiling); tvTiming.startTotal(); // create tv database bool isDbEmpty = databaseId.isNull(); if (isDbEmpty) { OdTvFactoryId tvFactoryId = odTvGetFactory(); databaseId = tvFactoryId.createDatabase(); } OdTvDatabasePtr pDb = databaseId.openObject(OdTv::kForWrite); if (isDbEmpty) OdTvDatabaseUtils::writeFileNameToTvDatabase(databaseId, filename); // create tv model tvModelId = pDb->createModel(filename); OdTvModelPtr pTvModel = tvModelId.openObject(OdTv::kForWrite); // create entity OdTvEntityId entId = pTvModel->appendEntity(OD_T("XML_ENTITY")); OdTvEntityPtr entPtr = entId.openObject(OdTv::kForWrite); // add geometry to created entity db->fillGeometry(entPtr); entPtr->setColor(OdTvColorDef(73, 56, 41), OdTvGeometryData::GeometryTypes::kFaces); entPtr->setColor(OdTvColorDef(250, 253, 15), OdTvGeometryData::GeometryTypes::kPolylines | OdTvGeometryData::GeometryTypes::kEdges); applyMaterial(pDb, entPtr); OdTvDatabaseUtils::createDeviceAndView(databaseId, tvModelId, OdTvGsView::RenderMode::kFlatShaded, true); OdTvMatrix m; m.setCoordSystem(OdTvPoint::kOrigin, OdTvVector::kXAxis * -1, OdTvVector::kYAxis, OdTvVector::kZAxis); tvModelId.openObject(OdTv::kForWrite)->setModelingMatrix(m); OdTvDevicesIteratorPtr deviceIter = databaseId.openObject(OdTv::kForWrite)->getDevicesIterator(); OdTvGsDevicePtr device = deviceIter->getDevice().openObject(OdTv::kForWrite); if (!device.isNull()) { device->setLineSmoothing(true); device->setOption(OdTvGsDevice::kAntiAliasLevel, 2.); device->setOption(OdTvGsDevice::kAntiAliasLevelExt, 0.25); } if (pProfileRes) pProfileRes->setCDATreeCreationTime(OdInt64((timing.getMiscTime()) * 1000.)); tvTiming.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64((timing.getTotalTime() - timing.getVectorizingTime()) * 1000.)); #if !defined(__APPLE__) pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime()) * 1000.)); pProfileRes->setTvTime(OdInt64((tvTiming.getTotalTime()) * 1000.)); #else pProfileRes->setVectorizingTime(OdInt64((timing.getVectorizingTime() + tvTiming.getTotalTime()) * 1000.)); #endif } ::odrxDynamicLinker()->unloadUnreferenced(); return true; } OdTvDatabaseId OdTvVisualizeXmlFiler::generate(OdTvFilerTimeProfiling* pProfileRes) const { // does nothing return OdTvDatabaseId(); } OdTvModelId OdTvVisualizeXmlFiler::appendFrom(const OdTvDatabaseId& databaseId, OdDbBaseDatabase* pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { if (rc) *rc = tvNotImplementedYet; return OdTvModelId(); } OdTvModelId OdTvVisualizeXmlFiler::appendFrom(const OdTvDatabaseId& databaseId, OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvDatabaseId tvDbId; OdTvModelId modelId; LoadXmlOptions opt(pBuffer); importXml(tvDbId, modelId, opt, pProfileRes, rc); return modelId; } OdTvModelId OdTvVisualizeXmlFiler::appendFrom(const OdTvDatabaseId& databaseId, const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvDatabaseId tvDbId; OdTvModelId modelId; LoadXmlOptions opt(filePath); importXml(tvDbId, modelId, opt, pProfileRes, rc); return modelId; } void OdTvXml2VisualizeFilerModule::initApp() { OdStaticRxObject svc; OdLandInitalize(&svc); odTvInitialize(); } void OdTvXml2VisualizeFilerModule::uninitApp() { OdLandUninitalize(); odTvUninitialize(); }