/////////////////////////////////////////////////////////////////////////////// // 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 "DgAutoplantTorusImpl.h" #include "DgAutoplantTorus.h" #include "DgXAttribute.h" #include "DgAutoplantEntityProperties.h" #include "Ge/GePlane.h" #include "Ge/GeLine3d.h" //============================================================================================== // // OdDgAutoplantTorus // //============================================================================================== ODRX_CONS_DEFINE_MEMBERS(OdDgAutoplantTorus, OdDgProxyGraphicsElement, DGELEMENT_CONSTR) //============================================================================================== OdDgAutoplantTorus::OdDgAutoplantTorus() { set3dFormatFlag(true); setElementType(OdDgElement::kTypeExtraGraphicsElement); } //============================================================================================== OdUInt32 OdDgAutoplantTorus::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 OdDgAutoplantTorus::scaleDataAfterWorkingUnitsChange(double dScale) { return m_impl.scaleData(dScale); } //============================================================================================== bool OdDgAutoplantTorus::subWorldDraw(OdGiWorldDraw* pWd) const { return m_impl.subWorldDraw(pWd, this); } //============================================================================================== void OdDgAutoplantTorus::subViewportDraw(OdGiViewportDraw *pVd) const { return m_impl.subViewportDraw(pVd, this); } //============================================================================================== OdResult OdDgAutoplantTorus::subGetGeomExtents(OdGeExtents3d& extents) const { return m_impl.subGetGeomExtents(extents, this); } //============================================================================================== OdResult OdDgAutoplantTorus::subGetGeomExtents(const OdDgElementId& idView, OdGeExtents3d& extents) const { return m_impl.subGetGeomExtents(idView, extents, this); } //============================================================================================== OdResult OdDgAutoplantTorus::subExplode(OdRxObjectPtrArray& entitySet) const { return m_impl.subExplode(entitySet, this); } //============================================================================================== OdResult OdDgAutoplantTorus::transformBy(const OdGeMatrix3d& xfm) { assertWriteEnabled(); return m_impl.transformBy(xfm); } //============================================================================================== bool OdDgAutoplantTorus::allowToConvertFromElement(OdDgElement* pBaseElement) const { if (pBaseElement && (pBaseElement->getElementType() == OdDgElement::kTypeExtraGraphicsElement) && (OdDgElement::getElementExtendedType(pBaseElement) == (OdUInt64)(OdDgAutoplantTorus::kType)) ) { return true; } return false; } //============================================================================================== void OdDgAutoplantTorus::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 OdDgAutoplantTorus::dgnInFields(OdDgFiler* pFiler) { return m_impl.dgnInFields(pFiler); } //============================================================================================== void OdDgAutoplantTorus::dgnOutFields(OdDgFiler* pFiler) const { m_impl.dgnOutFields(pFiler); } //============================================================================================== OdUInt64 OdDgAutoplantTorus::getFlags() const { return m_impl.getFlags(); } //============================================================================================== void OdDgAutoplantTorus::setFlags(OdUInt64 uFlags) { assertWriteEnabled(); m_impl.setFlags(uFlags); } //============================================================================================== OdGePoint3d OdDgAutoplantTorus::getOrigin() const { return m_impl.getOrigin(); } //============================================================================================== void OdDgAutoplantTorus::setOrigin(const OdGePoint3d& ptOrigin) { assertWriteEnabled(); m_impl.setOrigin(ptOrigin); } //============================================================================================== OdGeVector3d OdDgAutoplantTorus::getDirection() const { return m_impl.getDirection(); } //============================================================================================== void OdDgAutoplantTorus::setDirection(const OdGeVector3d& vrDirection) { assertWriteEnabled(); m_impl.setDirection(vrDirection); } //============================================================================================== OdGeVector3d OdDgAutoplantTorus::getRefVector() const { return m_impl.getRefVector(); } //============================================================================================== void OdDgAutoplantTorus::setRefVector(const OdGeVector3d& vrRef) { assertWriteEnabled(); m_impl.setRefVector(vrRef); } //============================================================================================== double OdDgAutoplantTorus::getMajorRadius() const { return m_impl.getMajorRadius(); } //============================================================================================== void OdDgAutoplantTorus::setMajorRadius(double dRadius) { assertWriteEnabled(); m_impl.setMajorRadius(dRadius); } //============================================================================================== double OdDgAutoplantTorus::getMinorStartRadius() const { return m_impl.getMinorStartRadius(); } //============================================================================================== void OdDgAutoplantTorus::setMinorStartRadius(double dRadius) { assertWriteEnabled(); m_impl.setMinorStartRadius(dRadius); } //============================================================================================== double OdDgAutoplantTorus::getMinorEndRadius() const { return m_impl.getMinorEndRadius(); } //============================================================================================== void OdDgAutoplantTorus::setMinorEndRadius(double dRadius) { assertWriteEnabled(); m_impl.setMinorEndRadius(dRadius); } //============================================================================================== double OdDgAutoplantTorus::getStartAngle() const { return m_impl.getStartAngle(); } //============================================================================================== void OdDgAutoplantTorus::setStartAngle(double dAngle) { assertWriteEnabled(); m_impl.setStartAngle(dAngle); } //============================================================================================== double OdDgAutoplantTorus::getSweepAngle() const { return m_impl.getSweepAngle(); } //============================================================================================== void OdDgAutoplantTorus::setSweepAngle(double dAngle) { assertWriteEnabled(); m_impl.setSweepAngle(dAngle); } //============================================================================================== // CDA Properties for OdDgAutoplantTorus //============================================================================================== //----------------------------------------------------------------------------------------------------------------------- // property: Origin //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusOriginProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getOrigin(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusOriginProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setOrigin(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Direction //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusDirectionProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getDirection(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusDirectionProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setDirection(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Ref Vector //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusRefVectorProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getRefVector(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusRefVectorProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setRefVector(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Major Radius //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusMajorRadiusProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getMajorRadius(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusMajorRadiusProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setMajorRadius(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Minor Start Radius //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusMinorStartRadiusProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getMinorStartRadius(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusMinorStartRadiusProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setMinorStartRadius(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Minor End Radius //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusMinorEndRadiusProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getMinorEndRadius(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusMinorEndRadiusProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setMinorEndRadius(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Start Angle //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusStartAngleProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getStartAngle(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusStartAngleProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setStartAngle(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Sweep Angle //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusSweepAngleProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getSweepAngle(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusSweepAngleProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setSweepAngle(*rxvalue_cast(&value)); return eOk; } //----------------------------------------------------------------------------------------------------------------------- // property: Flags //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusFlagsProperty::subGetValue(const OdRxObject* pO, OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; value = pObj->getFlags(); return eOk; } //----------------------------------------------------------------------------------------------------------------------- OdResult OdDgAutoplantTorusFlagsProperty::subSetValue(OdRxObject* pO, const OdRxValue& value) const { OdDgAutoplantTorusPtr pObj = OdDgAutoplantTorus::cast(pO); if (pObj.isNull()) return eNotApplicable; pObj->setFlags(*rxvalue_cast(&value)); return eOk; } //============================================================================================== // Grip and snap points for OdDgAutoplantTorus //============================================================================================== OdResult OdDgAutoplantTorusGripPointsPE::getGripPoints(const OdDgElement* pEnt, OdGePoint3dArray& gripPoints)const { unsigned int size = gripPoints.size(); gripPoints.resize(size + 6); OdDgAutoplantTorusPtr pTorus = pEnt; OdGeVector3d vrRef = pTorus->getRefVector(); OdGeVector3d vrDir = pTorus->getDirection(); if (vrRef.isZeroLength()) { if (vrDir.isZeroLength()) { vrDir = OdGeVector3d::kZAxis; vrRef = OdGeVector3d::kXAxis; } else { vrRef = vrDir.perpVector(); vrRef.normalize(); } } else vrRef.normalize(); if (vrDir.isZeroLength()) vrDir = vrRef.perpVector(); else vrDir.normalize(); OdGeVector3d vrRefNorm; OdGeVector3d vrRefNormStart; OdGeVector3d vrRefNormEnd; if (vrDir.isParallelTo(vrRef)) vrRefNorm = vrDir.perpVector(); else vrRefNorm = vrDir.crossProduct(vrRef); vrRef = vrRefNorm.crossProduct(vrDir); OdGeVector3d vrRadius = vrRef; OdGeVector3d vrStart = vrRef; OdGeVector3d vrEnd = vrRef; vrRadius.rotateBy(pTorus->getStartAngle() + pTorus->getSweepAngle() / 2.0, vrDir); vrStart.rotateBy(pTorus->getStartAngle(), vrDir); vrEnd.rotateBy(pTorus->getStartAngle() + pTorus->getSweepAngle(), vrDir); gripPoints[size] = pTorus->getOrigin(); gripPoints[size + 1] = pTorus->getOrigin() + vrRadius * pTorus->getMajorRadius(); gripPoints[size + 2] = pTorus->getOrigin() + vrStart * pTorus->getMajorRadius(); gripPoints[size + 3] = pTorus->getOrigin() + vrEnd * pTorus->getMajorRadius(); gripPoints[size + 4] = pTorus->getOrigin() + vrStart * (pTorus->getMajorRadius() + pTorus->getMinorStartRadius()); gripPoints[size + 5] = pTorus->getOrigin() + vrEnd * (pTorus->getMajorRadius() + pTorus->getMinorEndRadius()); return eOk; } //============================================================================================== OdResult OdDgAutoplantTorusGripPointsPE::moveGripPointsAt(OdDgElement* pEnt, const OdIntArray& indices, const OdGeVector3d& offset) { unsigned size = indices.size(); if (size == 0) return eOk; OdDgAutoplantTorusPtr pTorus = pEnt; OdGeVector3d vrRef = pTorus->getRefVector(); OdGeVector3d vrDir = pTorus->getDirection(); if (vrRef.isZeroLength()) { if (vrDir.isZeroLength()) { vrDir = OdGeVector3d::kZAxis; vrRef = OdGeVector3d::kXAxis; } else { vrRef = vrDir.perpVector(); vrRef.normalize(); } } else vrRef.normalize(); if (vrDir.isZeroLength()) vrDir = vrRef.perpVector(); else vrDir.normalize(); OdGeVector3d vrRefNorm; OdGeVector3d vrRefNormStart; OdGeVector3d vrRefNormEnd; if (vrDir.isParallelTo(vrRef)) vrRefNorm = vrDir.perpVector(); else vrRefNorm = vrDir.crossProduct(vrRef); vrRef = vrRefNorm.crossProduct(vrDir); OdGeVector3d vrRadius = vrRef; OdGeVector3d vrStart = vrRef; OdGeVector3d vrEnd = vrRef; vrRadius.rotateBy(pTorus->getStartAngle() + pTorus->getSweepAngle() / 2.0, vrDir); vrStart.rotateBy(pTorus->getStartAngle(), vrDir); vrEnd.rotateBy(pTorus->getStartAngle() + pTorus->getSweepAngle(), vrDir); if (size > 1 || indices[0] == 6) { pTorus->transformBy(OdGeMatrix3d::translation(offset)); } else if (indices[0] == 0) { pTorus->setOrigin(pTorus->getOrigin() + offset); } else if (indices[0] == 1) { OdGePoint3d ptRadius = pTorus->getOrigin() + vrRadius * pTorus->getMajorRadius(); OdGeLine3d lineMajorRadius(pTorus->getOrigin(), vrRadius); OdGePoint3d ptNewRadius = ptRadius + offset; ptRadius = lineMajorRadius.closestPointTo(ptNewRadius); pTorus->setMajorRadius(pTorus->getOrigin().distanceTo(ptRadius)); } else if (indices[0] == 2) { OdGePoint3d ptStartAngle = pTorus->getOrigin() + vrStart * pTorus->getMajorRadius(); OdGePoint3d ptNewStartAngle = ptStartAngle + offset; OdGePlane planeTorus(pTorus->getOrigin(), vrDir); ptNewStartAngle = ptNewStartAngle.project(planeTorus, vrDir); OdGeVector3d vrNewStartAngle = ptNewStartAngle - pTorus->getOrigin(); if( !vrNewStartAngle.isZeroLength() ) { vrNewStartAngle.normalize(); double dAngle = pTorus->getStartAngle() - vrRef.angleTo(vrNewStartAngle, vrDir); pTorus->setStartAngle(vrRef.angleTo(vrNewStartAngle, vrDir)); pTorus->setSweepAngle(pTorus->getSweepAngle() + dAngle); } } else if (indices[0] == 3) { OdGePoint3d ptEndAngle = pTorus->getOrigin() + vrEnd * pTorus->getMajorRadius(); OdGePoint3d ptNewEndAngle = ptEndAngle + offset; OdGePlane planeTorus(pTorus->getOrigin(), vrDir); ptNewEndAngle = ptNewEndAngle.project(planeTorus, vrDir); OdGeVector3d vrNewEndAngle = ptNewEndAngle - pTorus->getOrigin(); if (!vrNewEndAngle.isZeroLength()) { vrNewEndAngle.normalize(); pTorus->setSweepAngle(vrStart.angleTo(vrNewEndAngle, vrDir)); } } else if (indices[0] == 4) { OdGePoint3d ptStartAngle = pTorus->getOrigin() + vrStart * pTorus->getMajorRadius(); OdGePoint3d ptStartRadius = ptStartAngle + vrStart * pTorus->getMinorStartRadius(); OdGePoint3d ptNewStartRadius = ptStartRadius + offset; OdGeLine3d lineStartRadius(ptStartAngle, vrStart); ptNewStartRadius = lineStartRadius.closestPointTo(ptNewStartRadius); pTorus->setMinorStartRadius(ptStartAngle.distanceTo(ptNewStartRadius)); } else { OdGePoint3d ptEndAngle = pTorus->getOrigin() + vrEnd * pTorus->getMajorRadius(); OdGePoint3d ptEndRadius = ptEndAngle + vrEnd * pTorus->getMinorEndRadius(); OdGePoint3d ptNewEndRadius = ptEndRadius + offset; OdGeLine3d lineEndRadius(ptEndAngle, vrEnd); ptNewEndRadius = lineEndRadius.closestPointTo(ptNewEndRadius); pTorus->setMinorEndRadius(ptEndAngle.distanceTo(ptNewEndRadius)); } return eOk; } //============================================================================================== OdResult OdDgAutoplantTorusGripPointsPE::getStretchPoints(const OdDgElement* pEnt, OdGePoint3dArray& stretchPoints) const { OdResult res = getGripPoints(pEnt, stretchPoints); if (res == eOk) { stretchPoints.resize(stretchPoints.size() - 1); } return res; } //============================================================================================== OdResult OdDgAutoplantTorusGripPointsPE::moveStretchPointsAt(OdDgElement* pEnt, const OdIntArray& indices, const OdGeVector3d& offset) { return moveGripPointsAt(pEnt, indices, offset); } //============================================================================================== OdResult OdDgAutoplantTorusGripPointsPE::getOsnapPoints(const OdDgElement* pEnt, OdDgElement::OsnapMode osnapMode, OdGsMarker gsSelectionMark, const OdGePoint3d& pickPoint, const OdGePoint3d& lastPoint, const OdGeMatrix3d& xWorldToEye, OdGePoint3dArray& snapPoints) const { OdDgAutoplantTorusPtr pTorus = pEnt; OdGeVector3d vrRef = pTorus->getRefVector(); OdGeVector3d vrDir = pTorus->getDirection(); if (vrRef.isZeroLength()) { if (vrDir.isZeroLength()) { vrDir = OdGeVector3d::kZAxis; vrRef = OdGeVector3d::kXAxis; } else { vrRef = vrDir.perpVector(); vrRef.normalize(); } } else vrRef.normalize(); if (vrDir.isZeroLength()) vrDir = vrRef.perpVector(); else vrDir.normalize(); OdGeVector3d vrRefNorm; OdGeVector3d vrRefNormStart; OdGeVector3d vrRefNormEnd; if (vrDir.isParallelTo(vrRef)) vrRefNorm = vrDir.perpVector(); else vrRefNorm = vrDir.crossProduct(vrRef); vrRef = vrRefNorm.crossProduct(vrDir); OdGeVector3d vrRadius = vrRef; OdGeVector3d vrStart = vrRef; OdGeVector3d vrEnd = vrRef; vrStart.rotateBy(pTorus->getStartAngle(), vrDir); vrEnd.rotateBy(pTorus->getStartAngle() + pTorus->getSweepAngle(), vrDir); switch (osnapMode) { case OdDgElement::kOsModeCen: { snapPoints.append(pTorus->getOrigin()); snapPoints.append(pTorus->getOrigin() + vrStart * pTorus->getMajorRadius() ); snapPoints.append(pTorus->getOrigin() + vrEnd * pTorus->getMajorRadius()); } break; case OdDgElement::kOsModeEnd: { OdGePoint3d ptStartR = pTorus->getOrigin() + vrStart * pTorus->getMajorRadius(); OdGePoint3d ptEndR = pTorus->getOrigin() + vrEnd * pTorus->getMajorRadius(); OdGeVector3d vrStartNorm = vrDir.crossProduct(vrStart); OdGeVector3d vrEndNorm = vrDir.crossProduct(vrEnd); for (OdUInt32 i = 0; i < 8; i++) { snapPoints.append(ptStartR + vrStart * pTorus->getMinorStartRadius()); snapPoints.append(ptEndR + vrEnd * pTorus->getMinorEndRadius()); vrStart.rotateBy(OdaPI4, vrStartNorm); vrEnd.rotateBy(OdaPI4, vrEndNorm); } } break; default: { } break; } return eOk; } //==============================================================================================