/////////////////////////////////////////////////////////////////////////////// // 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. /////////////////////////////////////////////////////////////////////////////// #include "OdaCommon.h" #include "AssocLineExampleActionBody.h" #include "DbBlockTable.h" #include "DbBlockTableRecord.h" #include "DbBlockReference.h" #include "DbLine.h" #include "DbRegion.h" #include "Db3dSolid.h" #include "DbAssocNetwork.h" #include "DbAssocActionParam.h" #include "DbAssocGeomDependency.h" #include "DbImpAssocActionBody.h" const int OdAssocLineExampleActionBody::kVersion = 1; ODRX_DEFINE_MEMBERS_EX(OdAssocLineExampleActionBody, // ClassName OdDbAssocActionBody, // ParentClass DBOBJECT_CONSTR, // DOCREATE OdDb::kDHL_1021, // DwgVer OdDb::kMRelease6, // MaintVer 1025, // nProxyFlags (kEraseAllowed | kDisableProxyWarning) L"OdAssocLineExampleActionBody", // DWG class name L"ODASSOCLINEEXAMPLEACTIONBODY", // DxfName L"ExAssocNetwork", // AppName OdRx::kMTLoading | OdRx::kHistoryAware); OdAssocLineExampleActionBody::OdAssocLineExampleActionBody() { m_pImpObj = static_cast(new OdDbImpAssocActionBody()); } OdAssocLineExampleActionBody::~OdAssocLineExampleActionBody() { } OdResult OdAssocLineExampleActionBody::dwgInFields(OdDbDwgFiler* pFiler) { OdDbAssocActionBody::dwgInFields(pFiler); m_blockRefId = pFiler->rdSoftPointerId(); return eOk; } void OdAssocLineExampleActionBody::dwgOutFields(OdDbDwgFiler* pFiler) const { OdDbAssocActionBody::dwgOutFields(pFiler); pFiler->wrSoftPointerId(m_blockRefId); } OdResult OdAssocLineExampleActionBody::evaluateLine() { OdDbAssocActionPtr pAction = OdDbAssocAction::cast(parentAction().safeOpenObject(OdDb::kForWrite)); OdDbBlockReferencePtr pBlockRef = m_blockRefId.safeOpenObject(OdDb::kForWrite); if (pBlockRef.isNull()) { pAction->setStatus(kErasedAssocStatus); return eNullEntityPointer; } //Getting the “solid” association parameter for the line drawing type bool bSolid = false; OdStringArray paramNames; pAction->ownedValueParamNames(paramNames); if (paramNames.contains(OD_T("solid"))) { OdDbEvalVariantPtr value = OdDbEvalVariant::init(OdInt32()); OdString sEmpty; OdValue::UnitType unitType = OdValue::kUnitless; if (pAction->getValueParam(L"solid", *value.get(), sEmpty, sEmpty, unitType) == eOk && value->getAsInt() > 0) bSolid = true; } OdDbBlockTableRecordPtr pBR = pBlockRef->blockTableRecord().openObject(OdDb::kForWrite); if (pBR.isNull()) return eNullEntityPointer; OdDbLinePtr pLine; OdDb3dSolidPtr pSolid; for (auto pIter = pBR->newIterator(); !pIter->done(); pIter->step()) { OdDbEntityPtr pEnt = pIter->entity(OdDb::kForWrite); if (pEnt->isKindOf(OdDbLine::desc())) pLine = pEnt; else if (pEnt->isKindOf(OdDb3dSolid::desc())) pSolid = pEnt; } OdGeVector3d lineAxis; OdUInt16 colorIndex(0); bool bFirstPnt(true); int nParamCount = pAction->paramCount(); for (int n = 0; n < nParamCount; n++) { OdDbObjectId paramId = pAction->paramAtIndex(n); OdDbAssocOsnapPointRefActionParamPtr osnapPointRefParam = paramId.safeOpenObject(); OdGePoint3d pnt; osnapPointRefParam->evaluatePointOverride(pnt); if (bFirstPnt) { pBlockRef->setPosition(pnt); bFirstPnt = false; } else { OdGeMatrix3d matr = OdGeMatrix3d::translation(OdGePoint3d::kOrigin - pBlockRef->position()); pLine->setEndPoint(pnt.transformBy(matr)); lineAxis = pLine->endPoint() - pLine->startPoint(); double L = lineAxis.length(); colorIndex = static_cast(L) % 255; pLine->setColorIndex(colorIndex); } } if (!pSolid.isNull()) { pSolid->createBox(0.0, 0.0, 0.0); //If the rendering style is “solid” add solid object if (bSolid) { OdGeVector3d baseAxis = OdGeVector3d::kZAxis; OdGeVector3d targetAxis = lineAxis; targetAxis.normalize(); OdGeMatrix3d translation = OdGeMatrix3d::translation(OdGePoint3d(0, 0, lineAxis.length() / 2.0) - OdGePoint3d::kOrigin); OdGeMatrix3d transform = OdGeMatrix3d::rotation( baseAxis.angleTo(targetAxis), baseAxis.crossProduct(targetAxis).normalize() ) * translation; pSolid->createFrustum(lineAxis.length(), 2.0, 2.0, 2.0); pSolid->transformBy(transform); pSolid->setColorIndex(colorIndex); } } pAction->evaluateDependencies(); //Changing the status of the association to UpToDate pAction->setStatus(kIsUpToDateAssocStatus); return eOk; } int OdAssocLineExampleActionBody::getVersion() { return kVersion; } void OdAssocLineExampleActionBody::evaluateOverride() { evaluateLine(); } OdResult OdAssocLineExampleActionBody::createInstance( const OdDbFullSubentPathArray entPathArray, const OdGePoint3dArray& ptsSelected, const OdArray& snapModeArr, OdDbObjectId& blockRefId, OdDbObjectId& actionBodyId) { if (entPathArray.size() != 2 || snapModeArr.size() != 2) return eInvalidInput; OdDbObjectIdArray pathArray1 = entPathArray[0].objectIds(); OdDbObjectIdArray pathArray2 = entPathArray[1].objectIds(); OdDbObjectIdArray mainArray = pathArray1.isEmpty() ? pathArray2 : pathArray1; if (mainArray.isEmpty()) return eInvalidInput; OdDbObjectId ownerBTRId = mainArray[0].openObject()->ownerId(); OdDbBlockTableRecordPtr pOwnerSpace = ownerBTRId.safeOpenObject(OdDb::kForWrite); OdDbObjectId networkId = OdDbAssocNetwork::getInstanceFromObject(pOwnerSpace->objectId(), true); OdDbDatabase* pDb = mainArray[0].database(); OdDbObjectId actionId; //Creating the main action and the given action body if (eOk != createActionAndActionBodyAndPostToDatabase(desc(), networkId, actionId, actionBodyId)) return eInvalidInput; //Adding an action body to an action OdDbAssocActionPtr pAction = OdDbAssocAction::cast(actionId.openObject(OdDb::kForWrite)); pAction->setActionBody(actionBodyId); //Adding the “solid” parameter const OdDbEvalVariantPtr value = OdDbEvalVariant::init(OdInt32()); OdString errorMessage; pAction->setValueParam(OD_T("solid"), *value.get(), OD_T(""), OD_T(""), errorMessage, false, 0); //Creating Block Table Record And Block Reference to create and place a line OdDbObjectId lineId; createBlockRef(pDb, pOwnerSpace->objectId(), blockRefId, lineId); //Creating and adding a dependent reactor for the line that monitors it OdDbCompoundObjectId compoundObjectId; OdDbAssocDependencyPtr pDependency = OdDbAssocDependency::createObject(); pDb->addOdDbObject(pDependency); pDependency->setIsReadDependency(true); pDependency->setIsWriteDependency(true); compoundObjectId.set(blockRefId); pDependency->attachToObject(compoundObjectId); pAction->addDependency(pDependency->objectId(), true); //Create action parameters to provide access to anchor points and osnap type OdDbObjectId snapParamID1; OdResult res = OdDbAssocOsnapPointRefActionParam:: createInstanceAndPostToDatabase(actionBodyId, snapModeArr[0], entPathArray[0], ptsSelected[0], snapParamID1); if (res != eOk) return res; OdDbObjectId snapParamID2; res = OdDbAssocOsnapPointRefActionParam:: createInstanceAndPostToDatabase(actionBodyId, snapModeArr[1], entPathArray[1], ptsSelected[1], snapParamID2); if (res != eOk) return res; //Line recalculation OdAssocLineExampleActionBodyPtr pThisBody = actionBodyId.safeOpenObject(OdDb::kForWrite); pThisBody->setBlockRefId(blockRefId); res = pThisBody->evaluateLine(); return res; } OdResult OdAssocLineExampleActionBody::createBlockRef(OdDbDatabasePtr pDb, OdDbObjectId BTRId, OdDbObjectId& blockRefId, OdDbObjectId& lineId) { OdDbBlockTablePtr pMainBT = pDb->getBlockTableId().safeOpenObject(OdDb::kForWrite); OdDbBlockTableRecordPtr pDestinationBTR = OdDbBlockTableRecord::createObject(); OdString destinationBTRname = OD_T("*U"); pDestinationBTR->setName(destinationBTRname); pDb->addOdDbObject(pDestinationBTR, pMainBT->objectId()); //create line block reference OdDbBlockReferencePtr pLineBlockRef = OdDbBlockReference::createObject(); pLineBlockRef->setDatabaseDefaults(pDb); pLineBlockRef->setBlockTableRecord(pDestinationBTR->objectId()); blockRefId = pDb->addOdDbObject(pLineBlockRef, BTRId); OdDbLinePtr pLine = OdDbLine::createObject(); pLine->setStartPoint(OdGePoint3d::kOrigin); pLine->setEndPoint(OdGePoint3d(100.0, 0.0, 0.0)); pLine->setDatabaseDefaults(pDb); lineId = pDestinationBTR->appendOdDbEntity(pLine); OdDb3dSolidPtr pSolid = OdDb3dSolid::createObject(); pSolid->setDatabaseDefaults(pDb); pDestinationBTR->appendOdDbEntity(pSolid); pMainBT->add(pDestinationBTR); OdDbBlockTableRecordPtr pOwnerSpace = BTRId.safeOpenObject(OdDb::kForWrite); pOwnerSpace->appendOdDbEntity(pLineBlockRef); return eOk; }