/////////////////////////////////////////////////////////////////////////////// // 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 "StdAfx.h" #include "RxObjectImpl.h" #include "DgAutoplantBoxImpl.h" #include "DgAutoplantBox.h" #include "DgXAttribute.h" #include "DgAutoplantEntityProperties.h" #include "Ge/GePlane.h" #include "Ge/GeLine3d.h" //============================================================================================== // // OdDgAutoplantBox // //============================================================================================== ODRX_CONS_DEFINE_MEMBERS(OdDgAutoplantBox, OdDgProxyGraphicsElement, DGELEMENT_CONSTR) //============================================================================================== OdDgAutoplantBox::OdDgAutoplantBox() { set3dFormatFlag(true); setElementType(OdDgElement::kTypeExtraGraphicsElement); } //============================================================================================== OdUInt32 OdDgAutoplantBox::subSetAttributes(OdGiDrawableTraits* pTraits) const { OdUInt32 uRet = OdDgGraphicsElement::subSetAttributes(pTraits); OdGiSubEntityTraitsPtr pSubEntityTraits = OdGiSubEntityTraits::cast(pTraits); if (!pSubEntityTraits.isNull()) { pSubEntityTraits->setLineType(0); pSubEntityTraits->setLineWeight(OdDb::kLnWt000); } return uRet; } //============================================================================================== void OdDgAutoplantBox::scaleDataAfterWorkingUnitsChange(double dScale) { return m_impl.scaleData(dScale); } //============================================================================================== bool OdDgAutoplantBox::subWorldDraw(OdGiWorldDraw* pWd) const { return m_impl.subWorldDraw(pWd, this); } //============================================================================================== void OdDgAutoplantBox::subViewportDraw(OdGiViewportDraw *pVd) const { return m_impl.subViewportDraw(pVd, this); } //============================================================================================== OdResult OdDgAutoplantBox::subGetGeomExtents(OdGeExtents3d& extents) const { return m_impl.subGetGeomExtents(extents, this); } //============================================================================================== OdResult OdDgAutoplantBox::subGetGeomExtents(const OdDgElementId& idView, OdGeExtents3d& extents) const { return m_impl.subGetGeomExtents(idView, extents, this); } //============================================================================================== OdResult OdDgAutoplantBox::subExplode(OdRxObjectPtrArray& entitySet) const { return m_impl.subExplode(entitySet, this); } //============================================================================================== OdResult OdDgAutoplantBox::transformBy(const OdGeMatrix3d& xfm) { assertWriteEnabled(); return m_impl.transformBy(xfm); } //============================================================================================== bool OdDgAutoplantBox::allowToConvertFromElement(OdDgElement* pBaseElement) const { if (pBaseElement && (pBaseElement->getElementType() == OdDgElement::kTypeExtraGraphicsElement) && (OdDgElement::getElementExtendedType(pBaseElement) == (OdUInt64)(OdDgAutoplantBox::kType)) ) { return true; } return false; } //============================================================================================== void OdDgAutoplantBox::decomposeForSave() { OdRxObjectPtrArray arrXAttrs; getXAttributes(OdDgExtendedElementTypeXAttribute::kType, arrXAttrs); bool bAddXAttr = true; if( !arrXAttrs.isEmpty() ) { OdDgExtendedElementTypeXAttributePtr pXAttr = arrXAttrs[0]; if( !pXAttr.isNull() ) { bAddXAttr = pXAttr->getElementType() != (OdDgExtendedElementTypeXAttribute::OdDgExtendedElementType)(kType); if (bAddXAttr) removeXAttributes(OdDgExtendedElementTypeXAttribute::kType); } } if (bAddXAttr) { OdDgExtendedElementTypeXAttributePtr pXAttr = OdDgExtendedElementTypeXAttribute::createObject(); pXAttr->setElementType((OdDgExtendedElementTypeXAttribute::OdDgExtendedElementType)(kType)); pXAttr->setFlags(0); pXAttr->setXAttrId(1); addXAttribute(OdDgExtendedElementTypeXAttribute::kType, pXAttr); } } //============================================================================================== OdResult OdDgAutoplantBox::dgnInFields(OdDgFiler* pFiler) { return m_impl.dgnInFields(pFiler); } //============================================================================================== void OdDgAutoplantBox::dgnOutFields(OdDgFiler* pFiler) const { m_impl.dgnOutFields(pFiler); } //============================================================================================== OdGePoint3d OdDgAutoplantBox::getBaseCenter() const { return m_impl.getBaseCenter(); } //============================================================================================== void OdDgAutoplantBox::setBaseCenter(const OdGePoint3d& ptCenter) { assertWriteEnabled(); m_impl.setBaseCenter(ptCenter); } //============================================================================================== OdGePoint3d OdDgAutoplantBox::getTopCenter() const { return m_impl.getTopCenter(); } //============================================================================================== void OdDgAutoplantBox::setTopCenter(const OdGePoint3d& ptCenter) { assertWriteEnabled(); m_impl.setTopCenter(ptCenter); } //============================================================================================== OdGeVector3d OdDgAutoplantBox::getWidthDirection() const { return m_impl.getWidthDirection(); } //============================================================================================== void OdDgAutoplantBox::setWidthDirection(const OdGeVector3d& vrDirection) { assertWriteEnabled(); m_impl.setWidthDirection(vrDirection); } //============================================================================================== OdGeVector3d OdDgAutoplantBox::getTopCenterOffset() const { return m_impl.getTopCenterOffset(); } //============================================================================================== void OdDgAutoplantBox::setTopCenterOffset(const OdGeVector3d& vrOffset) { assertWriteEnabled(); m_impl.setTopCenterOffset(vrOffset); } //============================================================================================== double OdDgAutoplantBox::getBaseLength() const { return m_impl.getBaseLength(); } //============================================================================================== void OdDgAutoplantBox::setBaseLength(double dLength) { assertWriteEnabled(); m_impl.setBaseLength(dLength); } //============================================================================================== double OdDgAutoplantBox::getBaseWidth() const { return m_impl.getBaseWidth(); } //============================================================================================== void OdDgAutoplantBox::setBaseWidth(double dWidth) { assertWriteEnabled(); m_impl.setBaseWidth(dWidth); } //============================================================================================== double OdDgAutoplantBox::getTopLength() const { return m_impl.getTopLength(); } //============================================================================================== void OdDgAutoplantBox::setTopLength(double dLength) { assertWriteEnabled(); m_impl.setTopLength(dLength); } //============================================================================================== double OdDgAutoplantBox::getTopWidth() const { return m_impl.getTopWidth(); } //============================================================================================== void OdDgAutoplantBox::setTopWidth(double dWidth) { assertWriteEnabled(); m_impl.setTopWidth(dWidth); } //============================================================================================== OdUInt64 OdDgAutoplantBox::getFlags() const { return m_impl.getFlags(); } //============================================================================================== void OdDgAutoplantBox::setFlags(OdUInt64 uFlags) { assertWriteEnabled(); m_impl.setFlags(uFlags); } //============================================================================================== // CDA Properties for OdDgAutoplantBox //============================================================================================== //----------------------------------------------------------------------------------------------------------------------- // property: BaseCenter //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxBaseCenterProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getBaseCenter(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxBaseCenterProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setBaseCenter(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: TopCenter //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopCenterProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getTopCenter(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopCenterProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setTopCenter(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: WidthDirection //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxWidthDirectionProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getWidthDirection(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxWidthDirectionProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setWidthDirection(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: TopCenterOffset //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopCenterOffsetProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getTopCenterOffset(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopCenterOffsetProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setTopCenterOffset(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: BaseWidth //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxBaseWidthProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getBaseWidth(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxBaseWidthProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setBaseWidth(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: BaseLength //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxBaseLengthProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getBaseLength(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxBaseLengthProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setBaseLength(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: TopWidth //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopWidthProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getTopWidth(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopWidthProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setTopWidth(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: TopLength //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopLengthProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getTopLength(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxTopLengthProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setTopLength(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Flags //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxFlagsProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getFlags(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantBoxFlagsProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantBoxPtr pObj = OdDgAutoplantBox::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setFlags(*rxvalue_cast(&value)); return eOk; } //============================================================================================== // Grip and snap points for OdDgAutoplantCone //============================================================================================== OdResult OdDgAutoplantBoxGripPointsPE::getGripPoints(const OdDgElement* pEnt, OdGePoint3dArray& gripPoints)const { unsigned int size = gripPoints.size(); gripPoints.resize(size + 6); OdDgAutoplantBoxPtr pBox = pEnt; OdGeVector3d vrZDir = pBox->getTopCenter() - pBox->getBaseCenter(); if (vrZDir.isZeroLength()) vrZDir = OdGeVector3d::kZAxis; else vrZDir.normalize(); OdGeVector3d vrDir = pBox->getWidthDirection(); if (vrDir.isZeroLength()) vrDir = OdGeVector3d::kXAxis; else vrDir.normalize(); if (vrDir.isParallelTo(vrZDir)) vrZDir = vrDir.perpVector(); OdGeVector3d vrYDir = vrZDir.crossProduct(vrDir); if (vrYDir.isZeroLength()) vrYDir = OdGeVector3d::kYAxis; else vrYDir.normalize(); gripPoints[size] = pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0; gripPoints[size + 1] = pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 - vrYDir * pBox->getBaseLength() / 2.0; gripPoints[size + 2] = pBox->getBaseCenter() - vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0; gripPoints[size + 3] = pBox->getTopCenter() + pBox->getTopCenterOffset() + vrDir * pBox->getTopWidth() / 2.0 + vrYDir * pBox->getTopLength() / 2.0; return eOk; } //============================================================================================== OdResult OdDgAutoplantBoxGripPointsPE::moveGripPointsAt(OdDgElement* pEnt, const OdIntArray& indices, const OdGeVector3d& offset) { unsigned size = indices.size(); if (size == 0) return eOk; OdDgAutoplantBoxPtr pBox = pEnt; OdGeVector3d vrZDir = pBox->getTopCenter() - pBox->getBaseCenter(); if (vrZDir.isZeroLength()) vrZDir = OdGeVector3d::kZAxis; else vrZDir.normalize(); OdGeVector3d vrDir = pBox->getWidthDirection(); if (vrDir.isZeroLength()) vrDir = OdGeVector3d::kXAxis; else vrDir.normalize(); if (vrDir.isParallelTo(vrZDir)) vrZDir = vrDir.perpVector(); OdGeVector3d vrYDir = vrZDir.crossProduct(vrDir); if (vrYDir.isZeroLength()) vrYDir = OdGeVector3d::kYAxis; else vrYDir.normalize(); OdGeVector3d vrPlaneNorm = vrDir.crossProduct(vrYDir); if (!vrPlaneNorm.isZeroLength()) vrPlaneNorm.normalize(); else vrPlaneNorm = OdGeVector3d::kZAxis; if (size > 1 || indices[0] == 4) { pBox->transformBy(OdGeMatrix3d::translation(offset)); } else if (indices[0] == 0) { pBox->setBaseCenter(pBox->getBaseCenter() + offset); pBox->setTopCenter(pBox->getTopCenter() + offset); } else if (indices[0] == 3) { pBox->setTopCenter(pBox->getTopCenter() + offset); } else if (indices[0] == 1) { OdGePoint3d ptBase = pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0; OdGePoint3d ptLength = pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 - vrYDir * pBox->getBaseLength() / 2.0; OdGePoint3d ptNewLength = ptLength + offset; OdGeLine3d lineLength(ptBase, vrYDir); ptNewLength = lineLength.closestPointTo(ptNewLength); double dLengthOffset = ptNewLength.distanceTo(ptBase) - ptLength.distanceTo(ptBase); OdGeVector3d vrOffset = -vrYDir * dLengthOffset / 2.0; pBox->setBaseCenter(pBox->getBaseCenter() + vrOffset); pBox->setTopCenter(pBox->getTopCenter() + vrOffset); pBox->setBaseLength(pBox->getBaseLength() + dLengthOffset); pBox->setTopLength(pBox->getTopLength() + dLengthOffset); } else { OdGePoint3d ptBase = pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0; OdGePoint3d ptWidth = pBox->getBaseCenter() - vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0; OdGePoint3d ptNewWidth = ptWidth + offset; OdGeLine3d lineWidth(ptBase, vrDir); ptNewWidth = lineWidth.closestPointTo(ptNewWidth); double dWidthOffset = ptNewWidth.distanceTo(ptBase) - ptWidth.distanceTo(ptBase); OdGeVector3d vrOffset = -vrDir * dWidthOffset / 2.0; pBox->setBaseCenter(pBox->getBaseCenter() + vrOffset); pBox->setTopCenter(pBox->getTopCenter() + vrOffset); pBox->setBaseWidth(pBox->getBaseWidth() + dWidthOffset); pBox->setTopWidth(pBox->getTopWidth() + dWidthOffset); } return eOk; } //============================================================================================== OdResult OdDgAutoplantBoxGripPointsPE::getStretchPoints(const OdDgElement* pEnt, OdGePoint3dArray& stretchPoints) const { OdResult res = getGripPoints(pEnt, stretchPoints); if (res == eOk) { stretchPoints.resize(stretchPoints.size() - 1); } return res; } //============================================================================================== OdResult OdDgAutoplantBoxGripPointsPE::moveStretchPointsAt(OdDgElement* pEnt, const OdIntArray& indices, const OdGeVector3d& offset) { return moveGripPointsAt(pEnt, indices, offset); } //============================================================================================== OdResult OdDgAutoplantBoxGripPointsPE::getOsnapPoints(const OdDgElement* pEnt, OdDgElement::OsnapMode osnapMode, OdGsMarker gsSelectionMark, const OdGePoint3d& pickPoint, const OdGePoint3d& lastPoint, const OdGeMatrix3d& xWorldToEye, OdGePoint3dArray& snapPoints) const { OdDgAutoplantBoxPtr pBox = pEnt; OdGeVector3d vrZDir = pBox->getTopCenter() - pBox->getBaseCenter(); if (vrZDir.isZeroLength()) vrZDir = OdGeVector3d::kZAxis; else vrZDir.normalize(); OdGeVector3d vrDir = pBox->getWidthDirection(); if (vrDir.isZeroLength()) vrDir = OdGeVector3d::kXAxis; else vrDir.normalize(); if (vrDir.isParallelTo(vrZDir)) vrZDir = vrDir.perpVector(); OdGeVector3d vrYDir = vrZDir.crossProduct(vrDir); if (vrYDir.isZeroLength()) vrYDir = OdGeVector3d::kYAxis; else vrYDir.normalize(); OdGePoint3d ptBottom = pBox->getBaseCenter(); OdGePoint3d ptTop = pBox->getTopCenter(); ptTop += pBox->getTopCenterOffset(); switch (osnapMode) { case OdDgElement::kOsModeCen: { snapPoints.append(ptBottom); snapPoints.append(ptTop); } break; case OdDgElement::kOsModeEnd: { snapPoints.append(pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0); snapPoints.append(pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 - vrYDir * pBox->getBaseLength() / 2.0); snapPoints.append(pBox->getBaseCenter() - vrDir * pBox->getBaseWidth() / 2.0 - vrYDir * pBox->getBaseLength() / 2.0); snapPoints.append(pBox->getBaseCenter() - vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0); snapPoints.append(pBox->getTopCenter() + vrDir * pBox->getTopWidth() / 2.0 + vrYDir * pBox->getTopLength() / 2.0); snapPoints.append(pBox->getTopCenter() + vrDir * pBox->getTopWidth() / 2.0 - vrYDir * pBox->getTopLength() / 2.0); snapPoints.append(pBox->getTopCenter() - vrDir * pBox->getTopWidth() / 2.0 - vrYDir * pBox->getTopLength() / 2.0); snapPoints.append(pBox->getTopCenter() - vrDir * pBox->getTopWidth() / 2.0 + vrYDir * pBox->getTopLength() / 2.0); } break; case OdDgElement::kOsModeMid: { snapPoints.append(ptBottom); snapPoints.append(ptTop); OdGePoint3dArray arrBasePts; OdGePoint3dArray arrTopPts; arrBasePts.push_back(pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0); arrBasePts.push_back(pBox->getBaseCenter() + vrDir * pBox->getBaseWidth() / 2.0 - vrYDir * pBox->getBaseLength() / 2.0); arrBasePts.push_back(pBox->getBaseCenter() - vrDir * pBox->getBaseWidth() / 2.0 - vrYDir * pBox->getBaseLength() / 2.0); arrBasePts.push_back(pBox->getBaseCenter() - vrDir * pBox->getBaseWidth() / 2.0 + vrYDir * pBox->getBaseLength() / 2.0); arrTopPts.push_back(pBox->getTopCenter() + vrDir * pBox->getTopWidth() / 2.0 + vrYDir * pBox->getTopLength() / 2.0); arrTopPts.push_back(pBox->getTopCenter() + vrDir * pBox->getTopWidth() / 2.0 - vrYDir * pBox->getTopLength() / 2.0); arrTopPts.push_back(pBox->getTopCenter() - vrDir * pBox->getTopWidth() / 2.0 - vrYDir * pBox->getTopLength() / 2.0); arrTopPts.push_back(pBox->getTopCenter() - vrDir * pBox->getTopWidth() / 2.0 + vrYDir * pBox->getTopLength() / 2.0); for (OdUInt32 i = 0; i < 4; i++) { OdGeVector3d vrBaseToTop = arrTopPts[i] - arrBasePts[i]; snapPoints.append(arrBasePts[i] + vrBaseToTop / 2.0); } } break; default: { } break; } return eOk; } //==============================================================================================