/////////////////////////////////////////////////////////////////////////////// // 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. /////////////////////////////////////////////////////////////////////////////// /************************************************************************/ /* Implements notification functions for the evaluation of */ /* OdDHatch entities */ /************************************************************************/ #include "StdAfx.h" #include "ExHatchWatcher.h" #include "RxObjectImpl.h" #include "Ge/GeCurve2d.h" OdExHatchWatcherPE::OdExHatchWatcherPE() : _openCnt(0) { } void OdExHatchWatcherPE::modified(OdDbObject* pObj, const OdDbObject* pAssocObj) { if (_openCnt > 0) { OdDbObjectId objId = pObj->objectId(), assocId = pAssocObj->objectId(); IdAssocIdsMap::iterator it = _assocMap.find(objId); if (it == _assocMap.end()) { it = _assocMap.insert(_assocMap.end(), { objId, {} }); } if (!it->second.contains(assocId)) { it->second.push_back(assocId); } auto pModified = _selfModifiedHatches.find(objId); if (pModified != _selfModifiedHatches.end()) _selfModifiedHatches.erase(pModified); } } void OdExHatchWatcherPE::modifiedItself(OdDbHatch* pHatch) { if (_openCnt > 0) { OdDbObjectId hatchId = pHatch->objectId(); if (_assocMap.find(hatchId) == _assocMap.end()) _selfModifiedHatches.insert(hatchId); } } bool validateEdgesLoop(OdExHatchWatcherPE* hatchPE, OdDbHatch* pHatch, const int loopNum) { OdDbObjectIdArray idArr; pHatch->getAssocObjIdsAt(loopNum, idArr); if (!idArr.isEmpty()) { EdgeArray edgesHatch, edgesAssoc; pHatch->getLoopAt(loopNum, edgesHatch); struct EdgeArrayHeapController { ~EdgeArrayHeapController() { for (auto& rm : m_reference) delete rm; } EdgeArray m_reference; }m_edgeArrRemover; OdUInt32 loopType = 0; hatchPE->getLoopFromIds(pHatch, loopType, idArr, edgesAssoc); m_edgeArrRemover.m_reference = edgesAssoc; if (edgesAssoc.size() != edgesHatch.size()) { pHatch->setAssociative(false); return false; } const EdgeArray::value_type* const curveAssoc = edgesAssoc.asArrayPtr(); const EdgeArray::value_type* const curveHatch = edgesHatch.asArrayPtr(); for (EdgeArray::size_type j = 0; j < edgesAssoc.size(); ++j) { if (!curveAssoc[j]->operator==(*curveHatch[j])) { pHatch->setAssociative(false); return false; } } } return true; } void validateLoopsForAssociation(OdExHatchWatcherPE* hatchPE, OdDbHatch* pHatch) { const int numLoops = pHatch->numLoops(); for (int loopNum = 0; loopNum < numLoops; loopNum++) { OdUInt32 loopType = pHatch->loopTypeAt(loopNum); if (loopType & OdDbHatch::kPolyline) { pHatch->setAssociative(false); break; //TODO ODA curently do not support associative polyline loops } else { if (!validateEdgesLoop(hatchPE, pHatch, loopNum)) break; } } } void OdExHatchWatcherPE::update() { for (const auto& p: _assocMap) { if (auto pHatch = OdDbHatch::cast(p.first.openObject(OdDb::kForWrite))) evaluate(pHatch, p.second); } for (auto id: _selfModifiedHatches) { auto pHatch = OdDbHatch::cast(id.openObject(OdDb::kForWrite)); if (!pHatch.isNull() && pHatch->associative()) validateLoopsForAssociation(this, pHatch); } } void OdExHatchWatcherPE::clear() { _assocMap.clear(); _selfModifiedHatches.clear(); } void OdExHatchWatcherPE::open() { if (_openCnt == 0) { clear(); } ++_openCnt; } void OdExHatchWatcherPE::close(bool bUpdate) { if (_openCnt > 0) { if (--_openCnt == 0) { if (bUpdate) update(); clear(); } } }