/////////////////////////////////////////////////////////////////////////////// // 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 "AssocWireExampleActionBody.h" #include "DbBlockTable.h" #include "DbBlockTableRecord.h" #include "DbBlockReference.h" #include "DbLine.h" #include "DbAssocNetwork.h" #include "DbAssocActionParam.h" #include "DbAssocGeomDependency.h" #include "DbImpAssocActionBody.h" #include "COdPowerTowerEntity.h" #include "OdAssocPowerTowerPersSubentIdPE.h" const int OdAssocWireExampleActionBody::kVersion = 1; ODRX_DEFINE_MEMBERS_EX(OdAssocWireExampleActionBody, // ClassName OdDbAssocActionBody, // ParentClass DBOBJECT_CONSTR, // DOCREATE OdDb::kDHL_1021, // DwgVer OdDb::kMRelease6, // MaintVer 1025, // nProxyFlags (kEraseAllowed | kDisableProxyWarning) L"OdAssocWireExampleActionBody", // DWG class name L"ODASSOCWIREEXAMPLEACTIONBODY", // DxfName L"ExAssocNetwork", // AppName OdRx::kMTLoading | OdRx::kHistoryAware); OdAssocWireExampleActionBody::OdAssocWireExampleActionBody() { m_pImpObj = static_cast(new OdDbImpAssocActionBody()); } OdAssocWireExampleActionBody::~OdAssocWireExampleActionBody() { } OdResult OdAssocWireExampleActionBody::dwgInFields(OdDbDwgFiler* pFiler) { OdDbAssocActionBody::dwgInFields(pFiler); m_blockRefId = pFiler->rdSoftPointerId(); return eOk; } void OdAssocWireExampleActionBody::dwgOutFields(OdDbDwgFiler* pFiler) const { OdDbAssocActionBody::dwgOutFields(pFiler); pFiler->wrSoftPointerId(m_blockRefId); } OdResult OdAssocWireExampleActionBody::evaluateWire() { OdDbAssocActionPtr pAction = OdDbAssocAction::cast(parentAction().safeOpenObject(OdDb::kForWrite)); if (m_blockRefId.isErased()) { pAction->setStatus(kErasedAssocStatus); return eNullEntityPointer; } OdDbBlockReferencePtr pBlockRef = m_blockRefId.safeOpenObject(OdDb::kForWrite); if (pBlockRef.isNull()) { pAction->setStatus(kErasedAssocStatus); return eNullEntityPointer; } OdDbBlockTableRecordPtr pBR = pBlockRef->blockTableRecord().openObject(OdDb::kForWrite); if (pBR.isNull()) return eNullEntityPointer; OdDbSplinePtr pWire = OdDbSpline::cast(pBR->newIterator()->entity(OdDb::kForWrite)); 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()); OdGePoint3d endPnt = pnt.transformBy(matr); calcWireLine(OdGePoint3d(0, 0, 0), endPnt, pWire, pAction); } } pAction->evaluateDependencies(); pAction->setStatus(kIsUpToDateAssocStatus); return eOk; } void OdAssocWireExampleActionBody::calcWireLine(OdGePoint3d startPnt, OdGePoint3d endPnt, OdDbSpline* pWire, OdDbAssocActionPtr pAction) { if (!pWire) return; WireParams params = getWireParams(L"A-35"); double tensionPercentage = std::max(10.0, std::min(100.0, 30.0)); double horizontalTension = tensionPercentage * params.m_maxTension; //Getting the tension association parameter for the wire OdStringArray paramNames; pAction->ownedValueParamNames(paramNames); if (!paramNames.contains(OD_T("tension"))) { const OdDbEvalVariantPtr value = OdDbEvalVariant::init(horizontalTension); OdString errorMessage; pAction->setValueParam(OD_T("tension"), *value.get(), OD_T(""), OD_T(""), errorMessage, false, 0); } else { OdDbEvalVariantPtr value = OdDbEvalVariant::init(double()); OdString sEmpty; OdValue::UnitType unitType = OdValue::kUnitless; if (pAction->getValueParam(L"tension", *value.get(), sEmpty, sEmpty, unitType) == eOk) horizontalTension = value->getAsDouble(); } double L = startPnt.distanceTo(endPnt); if (L > 150e+3) horizontalTension *= 1.2; if (L > 300e+3) horizontalTension *= 1.5; int numFitPoints = 15; OdGePoint3dArray fitPoints; fitPoints.setLogicalLength(numFitPoints); for (int i = 0; i < numFitPoints; i++) { double t = (double)i / (numFitPoints - 1); double x = t * L; double sag = (params.m_weight * x * (L - x)) / (2 * horizontalTension); OdGePoint3d pt; pt.x = startPnt.x + t * (endPnt.x - startPnt.x); pt.y = startPnt.y + t * (endPnt.y - startPnt.y); pt.z = startPnt.z + t * (endPnt.z - startPnt.z) - sag; fitPoints[i] = pt; } //Set points to the wire spline pWire->purgeFitData(); pWire->setFitData(fitPoints, 3, 1e-6, OdGeVector3d(0, 0, 0), OdGeVector3d(0, 0, 0)); } int OdAssocWireExampleActionBody::getVersion() { return kVersion; } void OdAssocWireExampleActionBody::evaluateOverride() { evaluateWire(); } OdResult OdAssocWireExampleActionBody::addMoreObjectsToDeepCloneOverride( OdDbIdMapping& idMap, OdDbObjectIdArray& additionalObjectsToClone) const { OdDbIdPair actionPair(parentAction()); if (idMap.compute(actionPair)) return eOk; idMap.assign(actionPair); additionalObjectsToClone.append(parentAction()); OdDbBlockReferencePtr pBlockRef = m_blockRefId.safeOpenObject(OdDb::kForWrite); if (!pBlockRef.isNull()) additionalObjectsToClone.append(pBlockRef->blockTableRecord()); return eOk; } //void OdAssocWireExampleActionBody::clonePersSubentNamingDataOverride(OdDbAssocPersSubentManagerCloner* apsmc) //{ // OdDbAssocActionPtr pAction = OdDbAssocAction::cast(parentAction().safeOpenObject()); // if (pAction.isNull()) // return; // // OdDbObjectIdArray dependencyIds; // pAction->getDependencies(true, true, dependencyIds); // // for (const OdDbObjectId& depId : dependencyIds) // { // OdDbAssocGeomDependencyPtr pGeomDep = OdDbAssocGeomDependency::cast(depId.openObject()); // if (pGeomDep.isNull()) // continue; // // OdDbObjectId dependentOnObjectId = pGeomDep->dependentOnObject(); // if (dependentOnObjectId.isNull()) // continue; // // OdDbObjectPtr pDependentObj = dependentOnObjectId.openObject(); // if (pDependentObj.isNull()) // continue; // // COdPowerTowerEntityPtr pPowerTowerEntity = COdPowerTowerEntity::cast(pDependentObj); // if (!pPowerTowerEntity.isNull()) // { // OdAssocPowerTowerPersSubentIdPE::clonePersSubentId(pGeomDep.get(), pPowerTowerEntity.get(), apsmc); // } // } //} OdResult OdAssocWireExampleActionBody::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(); //Creating the main action and the given action body OdDbObjectId actionId; 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); //Creating Block Table Record And Block Reference to create and place a wire 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; //Wire recalculation OdAssocWireExampleActionBodyPtr pThisBody = actionBodyId.safeOpenObject(OdDb::kForWrite); pThisBody->setBlockRefId(blockRefId); pThisBody->evaluateWire(); return eOk; } OdResult OdAssocWireExampleActionBody::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 block reference with wire OdDbBlockReferencePtr pLineBlockRef = OdDbBlockReference::createObject(); pLineBlockRef->setDatabaseDefaults(pDb); pLineBlockRef->setBlockTableRecord(pDestinationBTR->objectId()); blockRefId = pDb->addOdDbObject(pLineBlockRef, BTRId); OdDbSplinePtr pWire = OdDbSpline::createObject(); pWire->setDatabaseDefaults(pDb); lineId = pDestinationBTR->appendOdDbEntity(pWire); pMainBT->add(pDestinationBTR); OdDbBlockTableRecordPtr pOwnerSpace = BTRId.safeOpenObject(OdDb::kForWrite); pOwnerSpace->appendOdDbEntity(pLineBlockRef); return eOk; }